A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
attribute-helper.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#ifndef ATTRIBUTE_HELPER_H
9#define ATTRIBUTE_HELPER_H
10
11#include "abort.h"
13#include "attribute.h"
14
15#include <sstream>
16
17/**
18 * @file
19 * @ingroup attributehelper
20 * Attribute helper (\c ATTRIBUTE_ )macros definition.
21 */
22
23namespace ns3
24{
25
26/**
27 * @ingroup attributes
28 * @defgroup attributehelper Attribute Helper
29 *
30 * All these macros can be used to generate automatically the code
31 * for subclasses of AttributeValue, AttributeAccessor, and, AttributeChecker,
32 * which can be used to give attribute powers to a normal class. i.e.,
33 * the user class can then effectively be made an attribute.
34 *
35 * There are two kinds of helper macros:
36 * -# The simple macros.
37 * - ATTRIBUTE_HELPER_HEADER(type)
38 * - ATTRIBUTE_HELPER_CPP(type)
39 * -# The more complex macros.
40 *
41 * The simple macros are implemented in terms of the complex
42 * macros and should generally be preferred over the complex macros.
43 *
44 * @note
45 * Because these macros generate class and function definitions, it's
46 * difficult to document the results directly. Instead, we use a
47 * set of functions in print-introspected-doxygen.cc to generate
48 * most of the APi documentation. When using these macros,
49 * please add the required function calls to print-introspected-doxygen.cc
50 * so your new API is documented.
51 */
52
53/**
54 * @ingroup attributehelper
55 * @defgroup attributeimpl Attribute Implementation
56 *
57 * These are the internal implementation functions for the Attribute
58 * system.
59 *
60 * Module code shouldn't need to call these directly. Instead,
61 * see \ref attributehelper.
62 *
63 * There are three versions of DoMakeAccessorHelperOne:
64 * - With a member variable: DoMakeAccessorHelperOne(U T::*)
65 * - With a class get functor: DoMakeAccessorHelperOne(U(T::*)() const)
66 * - With a class set method: DoMakeAccessorHelperOne(void(T::*)(U))
67 *
68 * There are two pairs of DoMakeAccessorHelperTwo (four total):
69 * - Taking two arguments, a set method and get functor, in either order,
70 * - With set methods returning \c void or \c bool.
71 */
72
73/**
74 * @ingroup attributeimpl
75 *
76 * A simple string-based attribute checker
77 *
78 * @tparam T \explicit The specific AttributeValue type used to represent
79 * the Attribute.
80 * @tparam BASE \explicit The AttributeChecker type corresponding to \pname{T}.
81 * @param [in] name The name of the AttributeValue type, essentially the
82 * string form of \pname{T}.
83 * @param [in] underlying Underlying type name.
84 * @return Ptr to AttributeChecker.
85 */
86template <typename T, typename BASE>
87Ptr<AttributeChecker>
88MakeSimpleAttributeChecker(std::string name, std::string underlying)
89{
90 /**
91 * String-based AttributeChecker implementation.
92 * @extends AttributeChecker
93 */
94 struct SimpleAttributeChecker : public BASE
95 {
96 bool Check(const AttributeValue& value) const override
97 {
98 return dynamic_cast<const T*>(&value) != nullptr;
99 }
100
101 std::string GetValueTypeName() const override
102 {
103 if (m_type.rfind("ns3::", 0) == 0)
104 {
105 // m_type already starts with "ns3::"
106 return m_type;
107 }
108 return "ns3::" + m_type;
109 }
110
111 bool HasUnderlyingTypeInformation() const override
112 {
113 return true;
114 }
115
116 std::string GetUnderlyingTypeInformation() const override
117 {
118 return m_underlying;
119 }
120
121 Ptr<AttributeValue> Create() const override
122 {
123 return ns3::Create<T>();
124 }
125
126 bool Copy(const AttributeValue& source, AttributeValue& destination) const override
127 {
128 const T* src = dynamic_cast<const T*>(&source);
129 T* dst = dynamic_cast<T*>(&destination);
130 if (src == nullptr || dst == nullptr)
131 {
132 return false;
133 }
134 *dst = *src;
135 return true;
136 }
137
138 std::string m_type; // The name of the AttributeValue type.
139 std::string m_underlying; // The underlying attribute type name.
140 }* checker = new SimpleAttributeChecker();
141
142 checker->m_type = name;
143 checker->m_underlying = underlying;
144 return Ptr<AttributeChecker>(checker, false);
145}
146
147} // namespace ns3
148
149/**
150 * @ingroup attributehelper
151 *
152 * Define the attribute accessor functions \c MakeTypeAccessor
153 * for class \pname{type}.
154 *
155 * @param [in] type The name of the class
156 *
157 * This macro defines and generates the code for the implementation
158 * of the \c MakeTypeAccessor template functions. This macro is typically
159 * invoked in a class header to allow users of this class to view and
160 * use the template functions defined here. This macro is implemented
161 * through the helper templates functions ns3::MakeAccessorHelper<>.
162 */
163#define ATTRIBUTE_ACCESSOR_DEFINE(type) \
164 template <typename T1> \
165 Ptr<const AttributeAccessor> Make##type##Accessor(T1 a1) \
166 { \
167 return MakeAccessorHelper<type##Value>(a1); \
168 } \
169 template <typename T1, typename T2> \
170 Ptr<const AttributeAccessor> Make##type##Accessor(T1 a1, T2 a2) \
171 { \
172 return MakeAccessorHelper<type##Value>(a1, a2); \
173 }
174
175/**
176 * @ingroup attributehelper
177 *
178 * Declare the attribute value class \pname{nameValue}
179 * for underlying class \pname{type}.
180 *
181 * @param [in] type The underlying type name token
182 * @param [in] name The token to use in defining the accessor name.
183 *
184 * This macro declares the class \c typeValue associated with class \c type.
185 * This macro is typically invoked in the class header file.
186 *
187 * This can be used directly for things like plain old data,
188 * such as \c std::string, to create the attribute value class
189 * StringValue, as in
190 * `ATTRIBUTE_VALUE_DEFINE_WITH_NAME(std::string, String);`
191 */
192#define ATTRIBUTE_VALUE_DEFINE_WITH_NAME(type, name) \
193 class name##Value : public AttributeValue \
194 { \
195 public: \
196 name##Value() = default; \
197 name##Value(const type& value); \
198 void Set(const type& value); \
199 type Get() const; \
200 template <typename T> \
201 bool GetAccessor(T& value) const \
202 { \
203 value = T(m_value); \
204 return true; \
205 } \
206 Ptr<AttributeValue> Copy() const override; \
207 std::string SerializeToString(Ptr<const AttributeChecker> checker) const override; \
208 bool DeserializeFromString(std::string value, \
209 Ptr<const AttributeChecker> checker) override; \
210 \
211 private: \
212 type m_value; \
213 }
214
215/**
216 * @ingroup attributehelper
217 *
218 * Declare the attribute value class \pname{nameValue}
219 * for the class \pname{name}
220 *
221 * @param [in] name The name of the class.
222 *
223 * This macro declares the class \c nameValue associated to class \c name.
224 * This macro is typically invoked in the class header file.
225 */
226#define ATTRIBUTE_VALUE_DEFINE(name) ATTRIBUTE_VALUE_DEFINE_WITH_NAME(name, name)
227
228/**
229 * @ingroup attributehelper
230 *
231 * Define the conversion operators class \pname{type} and
232 * Attribute instances.
233 *
234 * @param [in] type The name of the class
235 *
236 * This macro defines the conversion operators for class \c type to and
237 * from instances of \c typeAttribute.
238 * Typically invoked in the class header file.
239 *
240 * @internal
241 * This appears to be unused in the current code base.
242 */
243#define ATTRIBUTE_CONVERTER_DEFINE(type)
244
245/**
246 * @ingroup attributehelper
247 *
248 * Declare the AttributeChecker class \pname{typeChecker}
249 * and the \c MaketypeChecker function for class \pname{type}.
250 *
251 * @param [in] type The name of the class
252 *
253 * This macro declares the \pname{typeChecker} class and the associated
254 * \c MaketypeChecker function.
255 *
256 * (Note that the \pname{typeChecker} class needs no implementation
257 * since it just inherits all its implementation from AttributeChecker.)
258 *
259 * Typically invoked in the class header file.
260 */
261#define ATTRIBUTE_CHECKER_DEFINE(type) \
262 class type##Checker : public AttributeChecker \
263 { \
264 }; \
265 Ptr<const AttributeChecker> Make##type##Checker()
266
267/**
268 * @ingroup attributehelper
269 *
270 * Define the class methods belonging to
271 * the attribute value class \pname{nameValue}
272 * of the underlying class \pname{type}.
273 *
274 * @param [in] type The underlying type name
275 * @param [in] name The token to use in defining the accessor name.
276 *
277 * This macro implements the \pname{typeValue} class methods
278 * (including the \pname{typeValue}%::%SerializeToString
279 * and \pname{typeValue}%::%DeserializeFromString methods).
280 *
281 * Typically invoked in the source file
282 */
283#define ATTRIBUTE_VALUE_IMPLEMENT_WITH_NAME(type, name) \
284 name##Value::name##Value(const type& value) \
285 : m_value(value) \
286 { \
287 } \
288 void name##Value::Set(const type& v) \
289 { \
290 m_value = v; \
291 } \
292 type name##Value::Get() const \
293 { \
294 return m_value; \
295 } \
296 Ptr<AttributeValue> name##Value::Copy() const \
297 { \
298 return ns3::Create<name##Value>(*this); \
299 } \
300 std::string name##Value::SerializeToString(Ptr<const AttributeChecker> checker) const \
301 { \
302 std::ostringstream oss; \
303 oss << m_value; \
304 return oss.str(); \
305 } \
306 bool name##Value::DeserializeFromString(std::string value, \
307 Ptr<const AttributeChecker> checker) \
308 { \
309 if (value.empty()) \
310 { \
311 m_value = type(); \
312 return true; \
313 } \
314 std::istringstream iss; \
315 iss.str(value); \
316 iss >> m_value; \
317 NS_ABORT_MSG_UNLESS(iss.eof(), \
318 "Attribute value " \
319 << "\"" << value << "\"" \
320 << " is not properly formatted"); \
321 return !iss.bad() && !iss.fail(); \
322 }
323
324/**
325 * @ingroup attributehelper
326 *
327 * Define the class methods belonging to
328 * attribute value class \pname{typeValue} for class \pname{type}.
329 *
330 * @param [in] type The name of the class.
331 *
332 * This macro implements the \pname{typeValue} class methods
333 * (including the \pname{typeValue}%::%SerializeToString
334 * and \pname{typeValue}%::%DeserializeFromString methods).
335 *
336 * Typically invoked in the source file.
337 */
338#define ATTRIBUTE_VALUE_IMPLEMENT(type) ATTRIBUTE_VALUE_IMPLEMENT_WITH_NAME(type, type)
339
340/**
341 * @ingroup attributehelper
342 *
343 * Define the \c MaketypeChecker function for class \pname{type}.
344 *
345 * @param [in] type The name of the class
346 *
347 * This macro implements the \c MaketypeChecker function.
348 *
349 * Typically invoked in the source file..
350 */
351#define ATTRIBUTE_CHECKER_IMPLEMENT(type) \
352 Ptr<const AttributeChecker> Make##type##Checker() \
353 { \
354 return MakeSimpleAttributeChecker<type##Value, type##Checker>(#type "Value", #type); \
355 }
356
357/**
358 * @ingroup attributehelper
359 *
360 * Define the \c MaketypeChecker function for class \pname{type}.
361 *
362 * @param [in] type The name of the class.
363 * @param [in] name The string name of the underlying type.
364 *
365 * This macro implements the \c MaketypeChecker function
366 * for class \pname{type}.
367 *
368 * Typically invoked in the source file..
369 */
370#define ATTRIBUTE_CHECKER_IMPLEMENT_WITH_NAME(type, name) \
371 Ptr<const AttributeChecker> Make##type##Checker() \
372 { \
373 return MakeSimpleAttributeChecker<type##Value, type##Checker>(#type "Value", name); \
374 }
375
376/**
377 * @ingroup attributehelper
378 *
379 * Declare the attribute value, accessor and checkers for class \pname{type}
380 *
381 * @param [in] type The name of the class
382 *
383 * This macro declares:
384 *
385 * - The attribute value class \pname{typeValue},
386 *
387 * - The attribute accessor functions \c MaketypeAccessor,
388 *
389 * - The AttributeChecker class \pname{typeChecker},
390 * and the \c MaketypeChecker function,
391 *
392 * for class \pname{type}.
393 *
394 * This macro should be invoked outside of the class
395 * declaration in its public header.
396 */
397#define ATTRIBUTE_HELPER_HEADER(type) \
398 ATTRIBUTE_VALUE_DEFINE(type); \
399 ATTRIBUTE_ACCESSOR_DEFINE(type); \
400 ATTRIBUTE_CHECKER_DEFINE(type)
401
402/**
403 * @ingroup attributehelper
404 *
405 * Define the attribute value, accessor and checkers for class \pname{type}
406 *
407 * @param [in] type The name of the class
408 *
409 * This macro implements
410 *
411 * - The \pname{typeValue} class methods,
412 *
413 * - The \c MaketypeChecker function,
414 *
415 * for class \pname{type}.
416 *
417 * This macro should be invoked from the class implementation file.
418 */
419#define ATTRIBUTE_HELPER_CPP(type) \
420 ATTRIBUTE_CHECKER_IMPLEMENT(type); \
421 ATTRIBUTE_VALUE_IMPLEMENT(type)
422
423#endif /* ATTRIBUTE_HELPER_H */
NS_ABORT_x macro definitions.
ns3::MakeAccessorHelper declarations and template implementations.
ns3::AttributeValue, ns3::AttributeAccessor and ns3::AttributeChecker declarations.
Hold a value for an Attribute.
Definition attribute.h:59
Smart pointer class similar to boost::intrusive_ptr.
Ptr< AttributeChecker > MakeSimpleAttributeChecker(std::string name, std::string underlying)
A simple string-based attribute checker.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition ptr.h:604