A Discrete-Event Network Simulator
API
attribute-container.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Caliola Engineering, LLC.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Jared Dulmage <jared.dulmage@caliola.com>
18  */
19 
20 #ifndef ATTRIBUTE_CONTAINER_H
21 #define ATTRIBUTE_CONTAINER_H
22 
23 #include <ns3/attribute-helper.h>
24 #include <ns3/string.h>
25 
26 #include <algorithm>
27 #include <iterator>
28 #include <list>
29 #include <sstream>
30 #include <type_traits>
31 #include <typeinfo>
32 #include <utility>
33 
34 namespace ns3
35 {
36 
37 class AttributeChecker;
38 
39 // A = attribute value type, C = container type to return
50 template <class A, template <class...> class C = std::list>
52 {
53  public:
55  typedef A attribute_type;
57  typedef Ptr<A> value_type;
59  typedef std::list<value_type> container_type;
61  typedef typename container_type::const_iterator const_iterator;
63  typedef typename container_type::iterator iterator;
65  typedef typename container_type::size_type size_type;
67  typedef typename AttributeContainerValue::const_iterator Iterator; // NS3 type
68 
69  // use underlying AttributeValue to get return element type
71  typedef typename std::invoke_result_t<decltype(&A::Get), A> item_type;
73  typedef C<item_type> result_type;
74 
79  AttributeContainerValue(char sep = ',');
80 
86  template <class CONTAINER>
87  AttributeContainerValue(const CONTAINER& c);
88 
95  template <class ITER>
96  AttributeContainerValue(const ITER begin, const ITER end);
97 
99  ~AttributeContainerValue() override;
100 
101  // Inherited
102  Ptr<AttributeValue> Copy() const override;
103  bool DeserializeFromString(std::string value, Ptr<const AttributeChecker> checker) override;
104  std::string SerializeToString(Ptr<const AttributeChecker> checker) const override;
105 
106  // defacto pure virtuals to integrate with built-in accessor code
111  result_type Get() const;
120  template <class T>
121  void Set(const T& c);
130  template <typename T>
131  bool GetAccessor(T& value) const;
132 
133  // NS3 interface
138  size_type GetN() const;
143  Iterator Begin();
148  Iterator End();
149 
150  // STL-interface
155  size_type size() const;
160  iterator begin();
165  iterator end();
170  const_iterator begin() const;
175  const_iterator end() const;
176 
177  private:
188  template <class ITER>
189  Ptr<AttributeContainerValue<A, C>> CopyFrom(const ITER begin, const ITER end);
190 
191  char m_sep;
193 };
194 
196 {
197  public:
202  virtual void SetItemChecker(Ptr<const AttributeChecker> itemchecker) = 0;
208 };
209 
217 template <class A, template <class...> class C>
219 
227 template <class A, template <class...> class C = std::list>
229 
236 template <class A, template <class...> class C = std::list>
238 
249 template <typename A, template <typename...> class C = std::list, typename T1>
251 
265 template <typename A, template <typename...> class C = std::list, typename T1, typename T2>
267 
268 } // namespace ns3
269 
270 /*****************************************************************************
271  * Implementation below
272  *****************************************************************************/
273 
274 namespace ns3
275 {
276 
277 namespace internal
278 {
279 
286 template <class A, template <class...> class C>
288 {
289  public:
296  void SetItemChecker(Ptr<const AttributeChecker> itemchecker) override;
298 
299  private:
301 };
302 
303 template <class A, template <class...> class C>
305  : m_itemchecker(nullptr)
306 {
307 }
308 
309 template <class A, template <class...> class C>
311  : m_itemchecker(itemchecker)
312 {
313 }
314 
315 template <class A, template <class...> class C>
316 void
318 {
319  m_itemchecker = itemchecker;
320 }
321 
322 template <class A, template <class...> class C>
325 {
326  return m_itemchecker;
327 }
328 
329 } // namespace internal
330 
331 template <class A, template <class...> class C>
334 {
335  return MakeAttributeContainerChecker<A, C>();
336 }
337 
338 template <class A, template <class...> class C>
339 Ptr<const AttributeChecker>
341 {
342  auto checker = MakeAttributeContainerChecker<A, C>();
343  auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
344  acchecker->SetItemChecker(itemchecker);
345  return checker;
346 }
347 
348 template <class A, template <class...> class C>
349 Ptr<AttributeChecker>
351 {
352  std::string containerType;
353  std::string underlyingType;
355  {
356  std::ostringstream oss;
357  oss << "ns3::AttributeContainerValue<" << typeid(typename T::attribute_type).name() << ", "
358  << typeid(typename T::container_type).name() << ">";
359  containerType = oss.str();
360  }
361 
362  {
363  std::ostringstream oss;
364  oss << "ns3::Ptr<" << typeid(typename T::attribute_type).name() << ">";
365  underlyingType = oss.str();
366  }
367 
368  return MakeSimpleAttributeChecker<T, internal::AttributeContainerChecker<A, C>>(containerType,
369  underlyingType);
370 }
371 
372 template <class A, template <class...> class C>
374  : m_sep(sep)
375 {
376 }
377 
378 template <class A, template <class...> class C>
379 template <class CONTAINER>
381  : AttributeContainerValue<A, C>(c.begin(), c.end())
382 {
383 }
384 
385 template <class A, template <class...> class C>
386 template <class ITER>
389 {
390  CopyFrom(begin, end);
391 }
392 
393 template <class A, template <class...> class C>
395 {
396  m_container.clear();
397 }
398 
399 template <class A, template <class...> class C>
402 {
403  auto c = Create<AttributeContainerValue<A, C>>();
404  c->m_sep = m_sep;
405  c->m_container = m_container;
406  return c;
407 }
408 
409 template <class A, template <class...> class C>
410 bool
413 {
414  auto acchecker = DynamicCast<const AttributeContainerChecker>(checker);
415  if (!acchecker)
416  {
417  return false;
418  }
419 
420  std::istringstream iss(value); // copies value
421  while (std::getline(iss, value, m_sep))
422  {
423  auto avalue = acchecker->GetItemChecker()->CreateValidValue(StringValue(value));
424  if (!avalue)
425  {
426  return false;
427  }
428 
429  auto attr = DynamicCast<A>(avalue);
430  if (!attr)
431  {
432  return false;
433  }
434 
435  // TODO(jared): make insertion more generic?
436  m_container.push_back(attr);
437  }
438  return true;
439 }
440 
441 template <class A, template <class...> class C>
442 std::string
444 {
445  std::ostringstream oss;
446  bool first = true;
447  for (auto attr : *this)
448  {
449  if (!first)
450  {
451  oss << m_sep;
452  }
453  oss << attr->SerializeToString(checker);
454  first = false;
455  }
456  return oss.str();
457 }
458 
459 template <class A, template <class...> class C>
462 {
463  result_type c;
464  for (const value_type& a : *this)
465  {
466  c.insert(c.end(), a->Get());
467  }
468  return c;
469 }
470 
471 template <class A, template <class...> class C>
472 template <typename T>
473 bool
475 {
476  result_type src = Get();
477  value.clear();
478  std::copy(src.begin(), src.end(), std::inserter(value, value.end()));
479  return true;
480 }
481 
482 template <class A, template <class...> class C>
483 template <class T>
484 void
486 {
487  m_container.clear();
488  CopyFrom(c.begin(), c.end());
489 }
490 
491 template <class A, template <class...> class C>
494 {
495  return size();
496 }
497 
498 template <class A, template <class...> class C>
501 {
502  return begin();
503 }
504 
505 template <class A, template <class...> class C>
508 {
509  return end();
510 }
511 
512 template <class A, template <class...> class C>
515 {
516  return m_container.size();
517 }
518 
519 template <class A, template <class...> class C>
522 {
523  return m_container.begin();
524 }
525 
526 template <class A, template <class...> class C>
529 {
530  return m_container.end();
531 }
532 
533 template <class A, template <class...> class C>
536 {
537  return m_container.cbegin();
538 }
539 
540 template <class A, template <class...> class C>
543 {
544  return m_container.cend();
545 }
546 
547 template <class A, template <class...> class C>
548 template <class ITER>
550 AttributeContainerValue<A, C>::CopyFrom(const ITER begin, const ITER end)
551 {
552  for (ITER iter = begin; iter != end; ++iter)
553  {
554  m_container.push_back(Create<A>(*iter));
555  }
556  return this;
557 }
558 
559 template <typename A, template <typename...> class C, typename T1>
562 {
563  return MakeAccessorHelper<AttributeContainerValue<A, C>>(a1);
564 }
565 
566 template <typename A, template <typename...> class C, typename T1, typename T2>
567 Ptr<const AttributeAccessor>
569 {
570  return MakeAccessorHelper<AttributeContainerValue<A, C>>(a1, a2);
571 }
572 
573 } // namespace ns3
574 
575 #endif // ATTRIBUTE_CONTAINER_H
Represent the type of an attribute.
Definition: attribute.h:168
AttributeChecker implementation for AttributeContainerValue.
virtual Ptr< const AttributeChecker > GetItemChecker() const =0
Get the item checker.
virtual void SetItemChecker(Ptr< const AttributeChecker > itemchecker)=0
Set the item checker.
A container for one type of attribute.
result_type Get() const
Return a container of items.
Ptr< A > value_type
Type actually stored within the container.
void Set(const T &c)
Copy items from container c.
container_type::size_type size_type
Size type for container.
std::invoke_result_t< decltype(&A::Get), A > item_type
Item type of container returned by Get.
std::list< value_type > container_type
Internal container type.
container_type m_container
Internal container.
container_type::iterator iterator
stl-style Non-const iterator type.
~AttributeContainerValue() override
Destructor.
Iterator Begin()
NS3-style beginning of container.
iterator end()
STL-style end of container.
A attribute_type
AttributeValue (element) type.
std::string SerializeToString(Ptr< const AttributeChecker > checker) const override
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
AttributeContainerValue(char sep=',')
Default constructor.
C< item_type > result_type
Type of container returned.
bool GetAccessor(T &value) const
Set the given variable to the values stored by this TupleValue object.
container_type::const_iterator const_iterator
stl-style Const iterator type.
Ptr< AttributeContainerValue< A, C > > CopyFrom(const ITER begin, const ITER end)
Copy items from begin to end.
size_type GetN() const
NS3-style Number of items.
iterator begin()
STL-style beginning of container.
AttributeContainerValue::const_iterator Iterator
NS3 style iterator type.
Ptr< AttributeValue > Copy() const override
Iterator End()
NS3-style ending of container.
size_type size() const
STL-style number of items in container.
Hold a value for an Attribute.
Definition: attribute.h:70
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Hold variables of type string.
Definition: string.h:56
Ptr< const AttributeChecker > m_itemchecker
The AttributeChecker.
void SetItemChecker(Ptr< const AttributeChecker > itemchecker) override
Set the item checker.
Ptr< const AttributeChecker > GetItemChecker() const override
Get the item checker.
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeAttributeContainerAccessor(T1 a1)
Make AttributeContainerAccessor using explicit types.
Ptr< AttributeChecker > MakeAttributeContainerChecker(const AttributeContainerValue< A, C > &value)
Make AttributeContainerChecker from AttributeContainerValue.
value
Definition: second.py:41
#define list