A Discrete-Event Network Simulator
API
object-base.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2008 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20#include "object-base.h"
21#include "log.h"
24#include "string.h"
25#include "ns3/core-config.h"
26
27#include <cstdlib> // getenv
28#include <cstring> // strlen
29#include <unordered_map>
30
37namespace ns3 {
38
39NS_LOG_COMPONENT_DEFINE ("ObjectBase");
40
42
44namespace {
45
52std::pair<bool, std::string>
53EnvDictionary (std::string key)
54{
55 static std::unordered_map<std::string, std::string> dict;
56
57 if (dict.size () == 0)
58 {
59 const char *envVar = getenv ("NS_ATTRIBUTE_DEFAULT");
60 if (envVar != 0 && std::strlen (envVar) > 0)
61 {
62 std::string env = envVar;
63 std::string::size_type cur = 0;
64 std::string::size_type next = 0;
65 while (next != std::string::npos)
66 {
67 next = env.find (";", cur);
68 std::string tmp = std::string (env, cur, next - cur);
69 std::string::size_type equal = tmp.find ("=");
70 if (equal != std::string::npos)
71 {
72 std::string name = tmp.substr (0, equal);
73 std::string envval = tmp.substr (equal + 1, tmp.size () - equal - 1);
74 dict.insert ({name, envval});
75 }
76 cur = next + 1;
77 }
78 }
79 else
80 {
81 // insert an empty key, so we don't do this again
82 dict.insert ({"", ""});
83 }
84 }
85
86 std::string value;
87 bool found {false};
88
89 auto loc = dict.find (key);
90 if (loc != dict.end ())
91 {
92 value = loc->second;
93 found = true;
94 }
95 return {found, value};
96}
97
98} // unnamed namespace
99
100
109static TypeId
111{
113 TypeId tid = TypeId ("ns3::ObjectBase");
114 tid.SetParent (tid);
115 tid.SetGroupName ("Core");
116 return tid;
117}
118
119TypeId
121{
123 static TypeId tid = GetObjectIid ();
124 return tid;
125}
126
128{
129 NS_LOG_FUNCTION (this);
130}
131
132void
134{
135 NS_LOG_FUNCTION (this);
136}
137
144#ifdef NS3_LOG_ENABLE
145#define LOG_WHERE_VALUE(where, value) \
146 do { \
147 std::string valStr {"nothing"}; \
148 if (value) \
149 { \
150 valStr = "\"" + value->SerializeToString (info.checker) + "\""; \
151 } \
152 NS_LOG_DEBUG (where << " gave " << valStr); \
153 } while (false)
154#else
155#define LOG_WHERE_VALUE(where, value)
156#endif
157
158void
160{
161 // loop over the inheritance tree back to the Object base class.
162 NS_LOG_FUNCTION (this << &attributes);
163 TypeId tid = GetInstanceTypeId ();
164 do // Do this tid and all parents
165 {
166 // loop over all attributes in object type
167 NS_LOG_DEBUG ("construct tid=" << tid.GetName () <<
168 ", params=" << tid.GetAttributeN ());
169 for (uint32_t i = 0; i < tid.GetAttributeN (); i++)
170 {
171 struct TypeId::AttributeInformation info = tid.GetAttribute (i);
172 NS_LOG_DEBUG ("try to construct \"" << tid.GetName () << "::" <<
173 info.name << "\"");
174
175 Ptr<const AttributeValue> value = attributes.Find (info.checker);
176 std::string where = "argument";
177
178 LOG_WHERE_VALUE (where, value);
179 // See if this attribute should not be set here in the
180 // constructor.
181 if (!(info.flags & TypeId::ATTR_CONSTRUCT))
182 {
183 // Handle this attribute if it should not be
184 // set here.
185 if (value == 0)
186 {
187 // Skip this attribute if it's not in the
188 // AttributeConstructionList.
189 NS_LOG_DEBUG ("skipping, not settable at construction");
190 continue;
191 }
192 else
193 {
194 // This is an error because this attribute is not
195 // settable in its constructor but is present in
196 // the AttributeConstructionList.
197 NS_FATAL_ERROR ("Attribute name=" << info.name << " tid=" << tid.GetName () << ": initial value cannot be set using attributes");
198 }
199 }
200
201 if (!value)
202 {
203 auto [found, val] = EnvDictionary (tid.GetAttributeFullName (i));
204 if (found)
205 {
206 value = Create<StringValue> (val);
207 where = "env var";
208 LOG_WHERE_VALUE (where, value);
209 }
210 }
211
212 bool initial = false;
213 if (!value)
214 {
215 // Set from Tid initialValue, which is guaranteed to exist
216 value = info.initialValue;
217 where = "initial value";
218 initial = true;
219 LOG_WHERE_VALUE (where, value);
220 }
221
222 if (DoSet (info.accessor, info.checker, *value) || initial)
223 {
224 // Setting from initial value may fail, e.g. setting
225 // ObjectVectorValue from ""
226 // That's ok, so we still report success since construction is complete
227 NS_LOG_DEBUG ("construct \"" << tid.GetName () << "::" <<
228 info.name << "\" from " << where);
229 }
230
231 } // for i attributes
232 tid = tid.GetParent ();
233 }
234 while (tid != ObjectBase::GetTypeId ());
236
237}
238#undef LOG_WHERE_VALUE
239
240bool
243 const AttributeValue &value)
244{
245 NS_LOG_FUNCTION (this << accessor << checker << &value);
246 Ptr<AttributeValue> v = checker->CreateValidValue (value);
247 if (v == 0)
248 {
249 return false;
250 }
251 bool ok = accessor->Set (this, *v);
252 return ok;
253}
254
255void
256ObjectBase::SetAttribute (std::string name, const AttributeValue &value)
257{
258 NS_LOG_FUNCTION (this << name << &value);
260 TypeId tid = GetInstanceTypeId ();
261 if (!tid.LookupAttributeByName (name, &info))
262 {
263 NS_FATAL_ERROR ("Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName ());
264 }
265 if (!(info.flags & TypeId::ATTR_SET)
266 || !info.accessor->HasSetter ())
267 {
268 NS_FATAL_ERROR ("Attribute name=" << name << " is not settable for this object: tid=" << tid.GetName ());
269 }
270 if (!DoSet (info.accessor, info.checker, value))
271 {
272 NS_FATAL_ERROR ("Attribute name=" << name << " could not be set for this object: tid=" << tid.GetName ());
273 }
274}
275bool
276ObjectBase::SetAttributeFailSafe (std::string name, const AttributeValue &value)
277{
278 NS_LOG_FUNCTION (this << name << &value);
280 TypeId tid = GetInstanceTypeId ();
281 if (!tid.LookupAttributeByName (name, &info))
282 {
283 return false;
284 }
285 if (!(info.flags & TypeId::ATTR_SET)
286 || !info.accessor->HasSetter ())
287 {
288 return false;
289 }
290 return DoSet (info.accessor, info.checker, value);
291}
292
293void
294ObjectBase::GetAttribute (std::string name, AttributeValue &value) const
295{
296 NS_LOG_FUNCTION (this << name << &value);
298 TypeId tid = GetInstanceTypeId ();
299 if (!tid.LookupAttributeByName (name, &info))
300 {
301 NS_FATAL_ERROR ("Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName ());
302 }
303 if (!(info.flags & TypeId::ATTR_GET)
304 || !info.accessor->HasGetter ())
305 {
306 NS_FATAL_ERROR ("Attribute name=" << name << " is not gettable for this object: tid=" << tid.GetName ());
307 }
308 bool ok = info.accessor->Get (this, value);
309 if (ok)
310 {
311 return;
312 }
313 StringValue *str = dynamic_cast<StringValue *> (&value);
314 if (str == 0)
315 {
316 NS_FATAL_ERROR ("Attribute name=" << name << " tid=" << tid.GetName () << ": input value is not a string");
317 }
318 Ptr<AttributeValue> v = info.checker->Create ();
319 ok = info.accessor->Get (this, *PeekPointer (v));
320 if (!ok)
321 {
322 NS_FATAL_ERROR ("Attribute name=" << name << " tid=" << tid.GetName () << ": could not get value");
323 }
324 str->Set (v->SerializeToString (info.checker));
325}
326
327
328bool
329ObjectBase::GetAttributeFailSafe (std::string name, AttributeValue &value) const
330{
331 NS_LOG_FUNCTION (this << name << &value);
333 TypeId tid = GetInstanceTypeId ();
334 if (!tid.LookupAttributeByName (name, &info))
335 {
336 return false;
337 }
338 if (!(info.flags & TypeId::ATTR_GET)
339 || !info.accessor->HasGetter ())
340 {
341 return false;
342 }
343 bool ok = info.accessor->Get (this, value);
344 if (ok)
345 {
346 return true;
347 }
348 StringValue *str = dynamic_cast<StringValue *> (&value);
349 if (str == 0)
350 {
351 return false;
352 }
353 Ptr<AttributeValue> v = info.checker->Create ();
354 ok = info.accessor->Get (this, *PeekPointer (v));
355 if (!ok)
356 {
357 return false;
358 }
359 str->Set (v->SerializeToString (info.checker));
360 return true;
361}
362
363bool
365{
366 NS_LOG_FUNCTION (this << name << &cb);
367 TypeId tid = GetInstanceTypeId ();
369 if (accessor == 0)
370 {
371 return false;
372 }
373 bool ok = accessor->ConnectWithoutContext (this, cb);
374 return ok;
375}
376bool
377ObjectBase::TraceConnect (std::string name, std::string context, const CallbackBase &cb)
378{
379 NS_LOG_FUNCTION (this << name << context << &cb);
380 TypeId tid = GetInstanceTypeId ();
382 if (accessor == 0)
383 {
384 return false;
385 }
386 bool ok = accessor->Connect (this, context, cb);
387 return ok;
388}
389bool
391{
392 NS_LOG_FUNCTION (this << name << &cb);
393 TypeId tid = GetInstanceTypeId ();
395 if (accessor == 0)
396 {
397 return false;
398 }
399 bool ok = accessor->DisconnectWithoutContext (this, cb);
400 return ok;
401}
402bool
403ObjectBase::TraceDisconnect (std::string name, std::string context, const CallbackBase &cb)
404{
405 NS_LOG_FUNCTION (this << name << context << &cb);
406 TypeId tid = GetInstanceTypeId ();
408 if (accessor == 0)
409 {
410 return false;
411 }
412 bool ok = accessor->Disconnect (this, context, cb);
413 return ok;
414}
415
416
417
418} // namespace ns3
ns3::AttributeConstructionList declaration.
List of Attribute name, value and checker triples used to construct Objects.
Ptr< AttributeValue > Find(Ptr< const AttributeChecker > checker) const
Find an Attribute in the list from its AttributeChecker.
Hold a value for an Attribute.
Definition: attribute.h:69
Base class for Callback class.
Definition: callback.h:1196
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
bool TraceDisconnect(std::string name, std::string context, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected with a context.
Definition: object-base.cc:403
static TypeId GetTypeId(void)
Get the type ID.
Definition: object-base.cc:120
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:390
static TypeId GetObjectIid(void)
Ensure the TypeId for ObjectBase gets fully configured to anchor the inheritance tree properly.
Definition: object-base.cc:110
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
Definition: object-base.cc:159
virtual ~ObjectBase()
Virtual destructor.
Definition: object-base.cc:127
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:329
virtual void NotifyConstructionCompleted(void)
Notifier called once the ObjectBase is fully constructed.
Definition: object-base.cc:133
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:276
virtual TypeId GetInstanceTypeId(void) const =0
Get the most derived TypeId for this Object.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:294
bool TraceConnect(std::string name, std::string context, const CallbackBase &cb)
Connect a TraceSource to a Callback with a context.
Definition: object-base.cc:377
bool DoSet(Ptr< const AttributeAccessor > spec, Ptr< const AttributeChecker > checker, const AttributeValue &value)
Attempt to set the value referenced by the accessor spec to a valid value according to the checker,...
Definition: object-base.cc:241
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Hold variables of type string.
Definition: string.h:41
void Set(const std::string &value)
Set the value.
Definition: string.cc:31
a unique identifier for an interface.
Definition: type-id.h:59
std::size_t GetAttributeN(void) const
Get the number of attributes.
Definition: type-id.cc:1076
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
@ ATTR_SET
The attribute can be written.
Definition: type-id.h:65
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition: type-id.h:66
std::string GetAttributeFullName(std::size_t i) const
Get the Attribute name by index.
Definition: type-id.cc:1089
struct TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1083
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:929
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition: type-id.cc:1177
TypeId GetParent(void) const
Get the parent of this TypeId.
Definition: type-id.cc:943
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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 ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Debug message logging.
std::pair< bool, std::string > EnvDictionary(std::string key)
Get key, value pairs from the "NS_ATTRIBUTE_DEFAULT" environment variable.
Definition: object-base.cc:53
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
#define LOG_WHERE_VALUE(where, value)
Log where and what value we find for the attribute.
Definition: object-base.cc:145
ns3::ObjectBase declaration and NS_OBJECT_ENSURE_REGISTERED() madro definition.
ns3::StringValue attribute value declarations.
Attribute implementation.
Definition: type-id.h:78
std::string name
Attribute name.
Definition: type-id.h:80
Ptr< const AttributeAccessor > accessor
Accessor object.
Definition: type-id.h:90
uint32_t flags
AttributeFlags value.
Definition: type-id.h:84
Ptr< const AttributeChecker > checker
Checker object.
Definition: type-id.h:92
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:88
ns3::TraceSourceAccessor and ns3::MakeTraceSourceAccessor declarations.