Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / resource-encapsulation / include / RCSResourceAttributes.h
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /**
22  * @file
23  *
24  * This file contains the declaration of classes and its members related to RCSResourceAttributes
25  */
26 #ifndef RES_ENCAPSULATION_RESOURCEATTRIBUTES_H
27 #define RES_ENCAPSULATION_RESOURCEATTRIBUTES_H
28
29 // To avoid conflict using different boost::variant configuration with OC.
30 // It causes compile errors.
31 #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
32 #define BOOST_MPL_LIMIT_LIST_SIZE 30
33 #define BOOST_MPL_LIMIT_VECTOR_SIZE 30
34
35 #include <functional>
36 #include <unordered_map>
37 #include <vector>
38
39 #include "boost/variant.hpp"
40 #include "boost/mpl/contains.hpp"
41 #include "boost/mpl/find.hpp"
42 #include "boost/mpl/distance.hpp"
43 #include "boost/mpl/begin_end.hpp"
44 #include "boost/scoped_ptr.hpp"
45
46 #include "RCSException.h"
47
48 namespace OIC
49 {
50     namespace Service
51     {
52
53         /**
54         * This represents the attributes for a resource.
55         *
56         * It provides similar usage to c++ standard containers. (iterator,
57         * operators and accessors)<br/>
58         * An attribute value can be one of various types. <br/>
59         *
60         *
61         * @see Value
62         * @see Type
63         * @see iterator
64         * @see const_iterator
65         * @see RCSDiscoveryManager
66         * @see RCSRemoteResourceObject
67         * @see RCSResourceObject
68         */
69         class RCSResourceAttributes
70         {
71         private:
72             template< typename T > struct IsSupportedTypeHelper;
73
74             typedef boost::variant<
75                 std::nullptr_t,
76                 int,
77                 double,
78                 bool,
79                 std::string,
80                 RCSResourceAttributes,
81
82                 std::vector< int >,
83                 std::vector< double >,
84                 std::vector< bool >,
85                 std::vector< std::string >,
86                 std::vector< RCSResourceAttributes >,
87
88                 std::vector< std::vector< int > >,
89                 std::vector< std::vector< std::vector< int > > >,
90
91                 std::vector< std::vector< double > >,
92                 std::vector< std::vector< std::vector< double > > >,
93
94                 std::vector< std::vector< bool > >,
95                 std::vector< std::vector< std::vector< bool > > >,
96
97                 std::vector< std::vector< std::string > >,
98                 std::vector< std::vector< std::vector< std::string > > >,
99
100                 std::vector< std::vector< RCSResourceAttributes > >,
101                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
102             > ValueVariant;
103
104             template< typename T, typename V = void,
105                     typename = typename std::enable_if<
106                         IsSupportedTypeHelper< T >::type::value, V >::type >
107             struct enable_if_supported
108             {
109                 typedef V type;
110             };
111
112             template< typename VISITOR, typename MOVE = std::false_type >
113             class KeyValueVisitorHelper: public boost::static_visitor< >
114             {
115             public:
116                 KeyValueVisitorHelper(VISITOR& visitor) noexcept :
117                         m_visitor( visitor )
118                 {
119                 }
120
121                 template< typename T, typename M = MOVE >
122                 typename std::enable_if< std::is_same< M, std::false_type >::value >::type
123                 operator()(const std::string& key, const T& value) const
124                 {
125                     m_visitor(key, value);
126                 }
127
128                 template< typename T, typename M = MOVE >
129                 typename std::enable_if< std::is_same< M, std::true_type >::value >::type
130                 operator()(const std::string& key, T& value)
131                 {
132                     m_visitor(key, std::move(value));
133                 }
134
135             private:
136                 VISITOR& m_visitor;
137             };
138
139             template <typename T> struct IndexOfType;
140
141         public:
142
143             /**
144              * Trait class that identifies whether T is supported by the Value.
145              */
146             template< typename T >
147             struct is_supported_type: public std::conditional<
148                 IsSupportedTypeHelper< T >::type::value, std::true_type, std::false_type>::type { };
149
150             /**
151              * Identifiers for types of Value.
152              *
153              * @see Type
154              */
155             enum class TypeId
156             {
157                 NULL_T, /**< nullptr_t */
158                 INT, /**< int */
159                 DOUBLE, /**< double */
160                 BOOL, /**< bool */
161                 STRING, /**< std::string */
162                 ATTRIBUTES, /**< RCSResourceAttributes */
163                 VECTOR /**< std::vector */
164             };
165
166             /**
167              * A Helper class to identify types of Value.
168              *
169              * @see RCSResourceAttributes
170              * @see Value
171              * @see TypeId
172              */
173             class Type
174             {
175             public:
176                 Type(const Type&) = default;
177                 Type(Type&&) = default;
178
179                 Type& operator=(const Type&) = default;
180                 Type& operator=(Type&&) = default;
181
182                 /**
183                  * Returns type identifier.
184                  *
185                  * @return Identifier of type.
186                  *
187                  * @see getBaseTypeId
188                  */
189                 TypeId getId() const noexcept;
190
191                 /**
192                  * Returns the type identifier of a base type of sequence.
193                  *
194                  * For non sequence types, it is equivalent to calling getId.
195                  *
196                  * @return Identifier of type.
197                  *
198                  * @see getDepth
199                  * @see getId
200                  */
201                 static TypeId getBaseTypeId(const Type& t) noexcept;
202
203                 /**
204                  * Returns the depth of a type.
205                  *
206                  * The return will be zero for non sequence types.
207                  *
208                  * @see getBaseTypeId
209                  */
210                 static size_t getDepth(const Type& t) noexcept;
211
212                 /**
213                  * Factory method to create Type instance from T.
214                  *
215                  * @return An instance that has TypeId for T.
216                  *
217                  * @note T must be supported by Value. Otherwise, it won't compile.
218                  *
219                  * @see is_supported_type
220                  */
221                 template < typename T >
222                 constexpr static Type typeOf(const T&) noexcept
223                 {
224                     return Type{ IndexOfType< T >::value };
225                 }
226
227                 /**
228                  * Factory method to create Type instance from T.
229                  *
230                  * @return An instance that has TypeId for T.
231                  *
232                  * @note T must be supported by Value. Otherwise, it won't compile.
233                  *
234                  * @see is_supported_type
235                  */
236                 template < typename T >
237                 constexpr static Type typeOf() noexcept
238                 {
239                     return Type{ IndexOfType< T >::value };
240                 }
241
242                 //! @cond
243                 friend bool operator==(const Type&, const Type&) noexcept;
244                 //! @endcond
245
246             private:
247                 constexpr explicit Type(int which) noexcept :
248                     m_which{ which }
249                 {
250                 }
251
252             private:
253                 int m_which;
254             };
255
256             /**
257              * Value holds a value among various types at a time.
258              *
259              * Type helps identify type information of Value.
260              *
261              * Supported types are below
262              * @code
263                 int
264                 double
265                 bool
266                 std::string
267                 RCSResourceAttributes
268
269                 std::vector< int >
270                 std::vector< double >
271                 std::vector< bool >
272                 std::vector< std::string >
273                 std::vector< RCSResourceAttributes >
274
275                 std::vector< std::vector< int > >
276                 std::vector< std::vector< std::vector< int > > >
277
278                 std::vector< std::vector< double > >
279                 std::vector< std::vector< std::vector< double > > >
280
281                 std::vector< std::vector< bool > >
282                 std::vector< std::vector< std::vector< bool > > >
283
284                 std::vector< std::vector< std::string > >
285                 std::vector< std::vector< std::vector< std::string > > >
286
287                 std::vector< std::vector< RCSResourceAttributes > >
288                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
289              * @endcode
290              *
291              * @see RCSResourceAttributes
292              * @see Type
293              * @see is_supported_type
294              */
295             class Value
296             {
297             public:
298                 class ComparisonHelper;
299
300                 Value();
301                 Value(const Value&);
302                 Value(Value&&) noexcept;
303
304                 /**
305                  * Constructs a Value if T is a supported type.<br/>
306                  *       Otherwise it won't compile.
307                  */
308                 template< typename T, typename = typename enable_if_supported< T >::type >
309                 Value(T&& value) :
310                         m_data{ new ValueVariant{ std::forward< T >(value) } }
311                 {
312                 }
313
314                 Value(const char*);
315
316                 Value& operator=(const Value&);
317                 Value& operator=(Value&&);
318
319                 template< typename T, typename = typename enable_if_supported< T >::type >
320                 Value& operator=(T&& rhs)
321                 {
322                     *m_data = std::forward< T >(rhs);
323                     return *this;
324                 }
325
326                 Value& operator=(const char*);
327                 Value& operator=(std::nullptr_t);
328
329                 /**
330                  * Returns the underlying value as T.
331                  *
332                  * @return const reference to the underlying value.
333                  *
334                  * @throws BadGetException If type of the underlying value is not T.
335                  */
336                 template< typename T >
337                 typename std::add_lvalue_reference< const T >::type get() const
338                 {
339                     return checkedGet< T >();
340                 }
341
342                 /**
343                  * Returns the underlying value as T.
344                  *
345                  * @return reference to the underlying value.
346                  *
347                  * @throws BadGetException If type of the underlying value is not T.
348                  */
349                 template< typename T >
350                 typename std::add_lvalue_reference< T >::type get()
351                 {
352                     return checkedGet< T >();
353                 }
354
355                 /**
356                  * Returns Type information.
357                  *
358                  * @see Type
359                  */
360                 Type getType() const;
361
362                 /**
363                  * Returns a string representation.
364                  *
365                  */
366                 std::string toString() const;
367
368                 /**
369                  * Exchanges the content of the object by the content of the parameter.
370                  */
371                 void swap(Value&) noexcept;
372
373                 //! @cond
374                 friend class RCSResourceAttributes;
375                 //! @endcond
376
377             private:
378                 template< typename T, typename = typename enable_if_supported< T >::type >
379                 typename std::add_lvalue_reference< T >::type checkedGet() const
380                 {
381                     try
382                     {
383                         return boost::get< T >(*m_data);
384                     }
385                     catch (const boost::bad_get&)
386                     {
387                         throw RCSBadGetException{ "Wrong type" };
388                     }
389                 }
390
391                 template< typename T, typename U >
392                 bool equals(const U& rhs) const
393                 {
394                     try
395                     {
396                         return get< T >() == rhs;
397                     }
398                     catch (const RCSBadGetException&)
399                     {
400                         return false;
401                     }
402                 }
403
404             private:
405                 boost::scoped_ptr< ValueVariant > m_data;
406             };
407
408             class KeyValuePair;
409             class iterator;
410             class const_iterator;
411
412         public:
413             RCSResourceAttributes() = default;
414             RCSResourceAttributes(const RCSResourceAttributes&) = default;
415             RCSResourceAttributes(RCSResourceAttributes&&) = default;
416
417             RCSResourceAttributes& operator=(const RCSResourceAttributes&) = default;
418             RCSResourceAttributes& operator=(RCSResourceAttributes&&) = default;
419
420             /**
421              * Returns an {@link iterator} referring to the first element.
422              */
423             iterator begin() noexcept;
424
425             /**
426              * Returns an {@link iterator} referring to the <i>past-the-end element</i>.
427              */
428             iterator end() noexcept;
429
430             /**
431              * @copydoc cbegin()
432              */
433             const_iterator begin() const noexcept;
434
435             /**
436              * @copydoc cend()
437              */
438             const_iterator end() const noexcept;
439
440             /**
441              * Returns a const_iterator referring to the first element.
442              */
443             const_iterator cbegin() const noexcept;
444
445             /**
446              * Returns a const_iterator referring to the <i>past-the-end element</i>.
447              */
448             const_iterator cend() const noexcept;
449
450             /**
451              * Accesses a value.
452              *
453              * If @a key matches the key of a value,
454              * returns a reference to its mapped value. <br/>
455              * If @a key doesn't match the key of any value,
456              * inserts a new value with that key and returns a reference to it.
457              * The element is a Value that has null.
458              *
459              * @param key Key of the element whose mapped value is accessed.
460              *
461              * @return A reference to the mapped value with @a key.
462              *
463              * @see at
464              */
465             Value& operator[](const std::string& key);
466
467             /**
468              * Accesses a value.
469              *
470              * If @a key matches the key of a value,
471              * returns a reference to its mapped value. <br/>
472              * If @a key doesn't match the key of any value,
473              * inserts a new value with that key and returns a reference to it.
474              * The value has null.
475              *
476              * @param key Key of the element whose mapped value is accessed.
477              *        This is moved instead of copied when a new value is inserted.
478              *
479              * @return A reference to the mapped value with @a key.
480              *
481              * @see at
482              */
483             Value& operator[](std::string&& key);
484
485             /**
486              * Accesses a value.
487              *
488              * If @a key matches the key of a value,
489              * returns a reference to its mapped value. <br/>
490              * If @a key doesn't match the key of any value, throws InvalidKeyException.
491              *
492              * @param key Key of the element whose mapped value is accessed.
493              *
494              * @throws InvalidKeyException If @a key doesn't match the key of any value.
495              *
496              * @return A reference to the mapped value with @a key.
497              *
498              * @see operator[]
499              */
500             Value& at(const std::string& key);
501
502             /**
503               * Accesses a value.
504               *
505               * If @a key matches the key of a value,
506               * returns a reference to its mapped value. <br/>
507               * If @a key doesn't match the key of any value, throws InvalidKeyException.
508               *
509               * @param key Key of the element whose mapped value is accessed.
510               *
511               * @throws InvalidKeyException If @a key doesn't match the key of any value.
512               *
513               * @return A const reference to the mapped value with @a key.
514               *
515               * @see operator[]
516               */
517             const Value& at(const std::string& key) const;
518
519             /**
520              * Removes all elements.
521              */
522             void clear() noexcept;
523
524             /**
525              * Removes a single element.
526              *
527              * @param key Key of the element to be removed.
528              *
529              * @return true if an element is erased, false otherwise.
530              */
531             bool erase(const std::string& key);
532
533             /**
534              * Removes a single element.
535              *
536              * @param pos Iterator to the element to remove.
537              *
538              * @return Iterator following the last removed element.
539              */
540             iterator erase(const_iterator pos);
541
542             /**
543              * Checks this contains an element for the specified key.
544              *
545              * @param key Key to check.
546              *
547              * @return true if an element exists, false otherwise.
548              */
549             bool contains(const std::string& key) const;
550
551             /**
552              * Returns whether it is empty.
553              *
554              * @see size
555              */
556             bool empty() const noexcept;
557
558             /**
559              * Returns the number of elements.
560              *
561              * @see empty
562              */
563             size_t size() const noexcept;
564
565         private:
566             template< typename VISITOR >
567             void visit(VISITOR& visitor) const
568             {
569                 KeyValueVisitorHelper< VISITOR > helper{ visitor };
570
571                 for (const auto& i : m_values)
572                 {
573                     boost::variant< const std::string& > key{ i.first };
574                     boost::apply_visitor(helper, key, *i.second.m_data);
575                 }
576             }
577
578             template< typename VISITOR >
579             void visitToMove(VISITOR& visitor)
580             {
581                 KeyValueVisitorHelper< VISITOR, std::true_type > helper{ visitor };
582
583                 for (auto& i : m_values)
584                 {
585                     boost::variant< const std::string& > key{ i.first };
586                     boost::apply_visitor(helper, key, *i.second.m_data);
587                 }
588             }
589
590         private:
591             std::unordered_map< std::string, Value > m_values;
592
593             //! @cond
594             friend class ResourceAttributesConverter;
595
596             friend bool operator==(const RCSResourceAttributes&, const RCSResourceAttributes&);
597             //! @endcond
598         };
599
600         /**
601          * A helper class to avoid obscure comparisons of values which are supported
602          * by RCSResourceAttributes::Value caused by implicitly converting a value
603          * to a RCSResourceAttributes::Value.
604          *
605          * @see Value
606          * @see RCSResourceAttributes
607          * @see is_supported_type
608          */
609         class RCSResourceAttributes::Value::ComparisonHelper
610         {
611         public:
612             ComparisonHelper(const Value&);
613
614             ComparisonHelper(const ComparisonHelper&) = delete;
615             ComparisonHelper& operator=(const ComparisonHelper&) = delete;
616
617             template< typename T >
618             typename std::enable_if< is_supported_type< T >::value, bool >::type equals(
619                     const T& v) const
620             {
621                 return m_valueRef.equals< T >(v);
622             }
623
624             bool equals(const std::string& v) const
625             {
626                 return m_valueRef.equals< std::string >(v);
627             }
628
629             bool operator==(const ComparisonHelper&) const;
630
631         private:
632             const Value& m_valueRef;
633         };
634
635         //! @cond
636         template< typename T >
637         struct RCSResourceAttributes::IsSupportedTypeHelper
638         {
639             typedef boost::mpl::contains< ValueVariant::types, typename std::decay< T >::type > type;
640         };
641
642         template < typename T >
643         struct RCSResourceAttributes::IndexOfType
644         {
645             static_assert(RCSResourceAttributes::is_supported_type< T >::value,
646                 "The type is not supported!");
647
648             typedef typename boost::mpl::find< ValueVariant::types, T >::type iter;
649             typedef typename boost::mpl::begin< ValueVariant::types >::type mpl_begin;
650
651             static constexpr int value = boost::mpl::distance< mpl_begin, iter >::value;
652         };
653
654         template < typename T > constexpr int RCSResourceAttributes::IndexOfType< T >::value;
655         //! @endcond
656
657         /**
658          * @relates RCSResourceAttributes::Type
659          *
660          * Checks if the objects are equal, that is, whether types are exactly same.
661          *
662          * @return true if the objects are equal, false otherwise.
663          */
664         bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
665                 noexcept;
666
667         /**
668          * @relates RCSResourceAttributes::Type
669          *
670          * Checks if the objects are not equal, that is, whether types are not exactly same.
671          *
672          * @return true if the objects are not equal, false otherwise.
673          */
674         bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
675                 noexcept;
676
677         /**
678          * @relates RCSResourceAttributes::Value
679          *
680          * Checks if the contents are equal, that is,
681          * whether types are matched and underlying values are equal.
682          *
683          * @return true if the contents are equal, false otherwise.
684          */
685         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper&,
686                 const RCSResourceAttributes::Value::ComparisonHelper&);
687
688         /**
689          * @relates RCSResourceAttributes::Value
690          *
691          * Checks if the contents are not equal, that is,
692          * whether types are not matched or underlying values are not equal.
693          *
694          * @return true if the contents are not equal, false otherwise.
695          */
696         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper&,
697                 const RCSResourceAttributes::Value::ComparisonHelper&);
698
699         //! @cond
700         template< typename T >
701         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
702             std::is_constructible< std::string, T >::value, bool >::type
703         operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
704         {
705             return lhs.equals(rhs);
706         }
707
708         template< typename T >
709         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
710                     std::is_constructible< std::string, T >::value, bool >::type
711         operator==(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
712         {
713             return rhs == lhs;
714         }
715
716         template< typename T >
717         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
718                     std::is_constructible< std::string, T >::value, bool >::type
719         operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
720         {
721             return !(lhs == rhs);
722         }
723
724         template< typename T >
725         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
726                     std::is_constructible< std::string, T >::value, bool >::type
727         operator!=(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
728         {
729             return !(rhs == lhs);
730         }
731         //! @endcond
732
733         /**
734           * @relates RCSResourceAttributes
735           *
736           * Checks if the attributes are equal, that is, whether contents are equal.
737           *
738           * @return true if the attributes are equal, false otherwise.
739           */
740         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs);
741
742         /**
743           * @relates RCSResourceAttributes
744           *
745           * Checks if the attributes are not equal, that is, whether contents are not equal.
746           *
747           * @return true if the attributes are not equal, false otherwise.
748           */
749         bool operator!=(const RCSResourceAttributes&, const RCSResourceAttributes&);
750
751         /**
752          * KeyValuePair is a class to access attribute's key and value of an element pointed by
753          * iterators of RCSResourceAttributes.
754          *
755          *
756          * @see RCSResourceAttributes
757          * @see iterator
758          * @see const_iterator
759          */
760         class RCSResourceAttributes::KeyValuePair
761         {
762         private:
763             class KeyVisitor: public boost::static_visitor< const std::string& >
764             {
765             public:
766                 result_type operator()(iterator*) const noexcept;
767                 result_type operator()(const_iterator*) const noexcept;
768             };
769
770             class ValueVisitor: public boost::static_visitor< Value& >
771             {
772             public:
773                 result_type operator()(iterator*) noexcept;
774                 result_type operator()(const_iterator*);
775             };
776
777             class ConstValueVisitor: public boost::static_visitor< const Value& >
778             {
779             public:
780                 result_type operator()(iterator*) const noexcept;
781                 result_type operator()(const_iterator*) const noexcept;
782             };
783
784         public:
785             const std::string& key() const noexcept;
786             const RCSResourceAttributes::Value& value() const noexcept;
787             RCSResourceAttributes::Value& value();
788
789         private:
790             KeyValuePair(const KeyValuePair&) = default;
791             KeyValuePair(boost::variant< iterator*, const_iterator* >&&) noexcept;
792
793             KeyValuePair& operator=(const KeyValuePair&) = default;
794
795         private:
796             boost::variant< iterator*, const_iterator* > m_iterRef;
797
798             KeyVisitor m_keyVisitor;
799             ValueVisitor m_valueVisitor;
800             ConstValueVisitor m_constValueVisitor;
801
802             //! @cond
803             friend class iterator;
804             friend class const_iterator;
805             //! @endcond
806         };
807
808         /**
809          * A forward iterator to KeyValuePair.
810          *
811          * @see RCSResourceAttributes
812          * @see KeyValuePair
813          * @see const_iterator
814          */
815         class RCSResourceAttributes::iterator:
816                 public std::iterator< std::forward_iterator_tag, RCSResourceAttributes::KeyValuePair >
817         {
818         private:
819             typedef std::unordered_map< std::string, Value >::iterator base_iterator;
820
821         public:
822             iterator();
823             iterator(const iterator&);
824
825             iterator& operator=(const iterator&);
826
827             reference operator*();
828             pointer operator->();
829
830             iterator& operator++();
831             iterator operator++(int);
832
833             bool operator==(const iterator&) const;
834             bool operator!=(const iterator&) const;
835
836         private:
837             explicit iterator(base_iterator&&);
838
839         private:
840             base_iterator m_cur;
841             RCSResourceAttributes::KeyValuePair m_keyValuePair;
842
843             //! @cond
844             friend class RCSResourceAttributes;
845             //! @endcond
846         };
847
848
849         /**
850          * A forward iterator to const KeyValuePair.
851          *
852          * @see RCSResourceAttributes
853          * @see KeyValuePair
854          * @see iterator
855          */
856         class RCSResourceAttributes::const_iterator:
857                 public std::iterator< std::forward_iterator_tag,
858                                        const RCSResourceAttributes::KeyValuePair >
859         {
860         private:
861             typedef std::unordered_map< std::string, Value >::const_iterator base_iterator;
862
863         public:
864             const_iterator();
865             const_iterator(const const_iterator&);
866             const_iterator(const RCSResourceAttributes::iterator&);
867
868             const_iterator& operator=(const const_iterator&);
869             const_iterator& operator=(const RCSResourceAttributes::iterator&);
870
871             reference operator*() const;
872             pointer operator->() const;
873
874             const_iterator& operator++();
875             const_iterator operator++(int);
876
877             bool operator==(const const_iterator&) const;
878             bool operator!=(const const_iterator&) const;
879
880         private:
881             explicit const_iterator(base_iterator&&);
882
883         private:
884             base_iterator m_cur;
885             RCSResourceAttributes::KeyValuePair m_keyValuePair;
886
887             //! @cond
888             friend class RCSResourceAttributes;
889             //! @endcond
890         };
891
892     }
893 }
894
895 #endif // RES_ENCAPSULATION_RESOURCEATTRIBUTES_H