Add doxygen comments for resource-encapsulation
[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 /** OIC namespace */
49 namespace OIC
50 {
51     namespace Service
52     {
53         /**
54         * This RCSByteString the one of RCSResourceAttributes value for Byte String (Binary).
55         *
56         * It provides similar usage to c++ standard vector.<br/>
57         * An RCSByteString can be one of various attribute value type.
58         *
59         * @see Value
60         * @see Type
61         * @see RCSRemoteResourceObject
62         * @see RCSResourceObject
63         * @see RCSResourceAttributes
64         */
65         class RCSByteString
66         {
67         public:
68             typedef std::vector<uint8_t> DataType;
69
70             /**
71              * Returns a vector<uint8_t> type of byte string.
72              *
73              * @return A stored byte string with std::vector<uint8_t>
74              */
75             DataType getByteString() const
76             {
77                 return {m_data};
78             }
79
80             /**
81              * Returns a size of stored vector<uint8_t>.
82              *
83              * @return A size of stored byte string.
84              */
85             size_t size() const
86             {
87                 return m_data.size();
88             }
89
90             /**
91               * @relates RCSByteString
92               *
93               * Checks if the byte string is same contents, or not.
94               *
95               * @return true if the byte string are equal, false otherwise.
96               */
97             inline bool operator==(const RCSByteString& rhs) const
98             {
99                 return this->m_data == rhs.getByteString();
100             }
101
102             /**
103              * @relates RCSByteString
104              *
105              * Checks if the byte string is not same contents, or is same.
106              *
107              * @return true if the byte string are not equal, false otherwise.
108              */
109             inline bool operator!=(const RCSByteString& rhs) const
110             {
111                 return this->m_data != rhs.getByteString();
112             }
113
114             /**
115              * Return a value of indexed byte string.
116              *
117              * @param it location of the element.
118              *
119              * @return A copied value of indexed byte string.
120              */
121             inline uint8_t operator[](size_t it) const
122             {
123                 return this->m_data[it];
124             }
125
126             RCSByteString()
127             {
128             }
129             RCSByteString(DataType && rhs)
130             : m_data {std::move(rhs)}
131             {
132             }
133             RCSByteString(const DataType & rhs)
134             : m_data {rhs}
135             {
136             }
137             RCSByteString(RCSByteString && rhs)
138             : m_data {DataType{rhs.getByteString()}}
139             {
140             }
141             RCSByteString(const RCSByteString & rhs)
142             : m_data {DataType{rhs.getByteString()}}
143             {
144             }
145
146             RCSByteString(::OCByteString && rhs)
147             : m_data {DataType{rhs.bytes, rhs.bytes + rhs.len}}
148             {
149             }
150             RCSByteString(const ::OCByteString & rhs)
151             : m_data {DataType{rhs.bytes, rhs.bytes + rhs.len}}
152             {
153             }
154
155             RCSByteString(uint8_t* bytes, size_t size)
156             : m_data {DataType{bytes, bytes + size}}
157             {
158             }
159             inline RCSByteString& operator=(RCSByteString&& rhs)
160             {
161                 return operator =(rhs);
162             }
163             inline RCSByteString& operator=(const RCSByteString& rhs)
164             {
165                 if(&rhs != this)
166                 {
167                     if (!m_data.empty())
168                     {
169                         m_data.clear();
170                     }
171                     m_data = DataType{rhs.getByteString()};
172                 }
173                 return *this;
174             }
175         private:
176             DataType m_data;
177         };
178
179         /**
180         * This represents the attributes for a resource.
181         *
182         * It provides similar usage to c++ standard containers. (iterator,
183         * operators and accessors)<br/>
184         * An attribute value can be one of various types. <br/>
185         *
186         *
187         * @see Value
188         * @see Type
189         * @see iterator
190         * @see const_iterator
191         * @see RCSDiscoveryManager
192         * @see RCSRemoteResourceObject
193         * @see RCSResourceObject
194         * @see RCSByteString
195         */
196         class RCSResourceAttributes
197         {
198         private:
199             template< typename T > struct IsSupportedTypeHelper;
200
201             typedef boost::variant<
202                 std::nullptr_t,
203                 int,
204                 double,
205                 bool,
206                 std::string,
207                 RCSByteString,
208                 RCSResourceAttributes,
209
210                 std::vector< int >,
211                 std::vector< double >,
212                 std::vector< bool >,
213                 std::vector< std::string >,
214                 std::vector< RCSByteString >,
215                 std::vector< RCSResourceAttributes >,
216
217                 std::vector< std::vector< int > >,
218                 std::vector< std::vector< std::vector< int > > >,
219
220                 std::vector< std::vector< double > >,
221                 std::vector< std::vector< std::vector< double > > >,
222
223                 std::vector< std::vector< bool > >,
224                 std::vector< std::vector< std::vector< bool > > >,
225
226                 std::vector< std::vector< std::string > >,
227                 std::vector< std::vector< std::vector< std::string > > >,
228
229                 std::vector< std::vector< RCSByteString > >,
230                 std::vector< std::vector< std::vector< RCSByteString > > >,
231
232                 std::vector< std::vector< RCSResourceAttributes > >,
233                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
234             > ValueVariant;
235
236             template< typename T, typename V = void,
237                     typename = typename std::enable_if<
238                         IsSupportedTypeHelper< T >::type::value, V >::type >
239             struct enable_if_supported
240             {
241                 typedef V type;
242             };
243
244             template< typename VISITOR, typename MOVE = std::false_type >
245             class KeyValueVisitorHelper: public boost::static_visitor< >
246             {
247             public:
248                 KeyValueVisitorHelper(VISITOR& visitor) BOOST_NOEXCEPT :
249                         m_visitor( visitor )
250                 {
251                 }
252
253                 template< typename T, typename M = MOVE >
254                 typename std::enable_if< std::is_same< M, std::false_type >::value >::type
255                 operator()(const std::string& key, const T& value) const
256                 {
257                     m_visitor(key, value);
258                 }
259
260                 template< typename T, typename M = MOVE >
261                 typename std::enable_if< std::is_same< M, std::true_type >::value >::type
262                 operator()(const std::string& key, T& value)
263                 {
264                     m_visitor(key, std::move(value));
265                 }
266
267             private:
268                 VISITOR& m_visitor;
269             };
270
271             template <typename T> struct IndexOfType;
272
273         public:
274
275             /**
276              * Trait class that identifies whether T is supported by the Value.
277              */
278             template< typename T >
279             struct is_supported_type: public std::conditional<
280                 IsSupportedTypeHelper< T >::type::value, std::true_type, std::false_type>::type { };
281
282             /**
283              * Identifiers for types of Value.
284              *
285              * @see Type
286              */
287             enum class TypeId
288             {
289                 NULL_T, /**< nullptr_t */
290                 INT, /**< int */
291                 DOUBLE, /**< double */
292                 BOOL, /**< bool */
293                 STRING, /**< std::string */
294                 BYTESTRING, /**< RCSByteString */
295                 ATTRIBUTES, /**< RCSResourceAttributes */
296                 VECTOR /**< std::vector */
297             };
298
299             /**
300              * A Helper class to identify types of Value.
301              *
302              * @see RCSResourceAttributes
303              * @see Value
304              * @see TypeId
305              */
306             class Type
307             {
308             public:
309                 Type(const Type&) = default;
310                 Type(Type&&) = default;
311
312                 Type& operator=(const Type&) = default;
313                 Type& operator=(Type&&) = default;
314
315                 /**
316                  * Returns type identifier.
317                  *
318                  * @return Identifier of type.
319                  *
320                  * @see getBaseTypeId
321                  */
322                 TypeId getId() const BOOST_NOEXCEPT;
323
324                 /**
325                  * Returns the type identifier of a base type of sequence.
326                  *
327                  * For non sequence types, it is equivalent to calling getId.
328                  *
329                  * @return Identifier of type.
330                  *
331                  * @see getDepth
332                  * @see getId
333                  */
334                 static TypeId getBaseTypeId(const Type& t) BOOST_NOEXCEPT;
335
336                 /**
337                  * Returns the depth of a type.
338                  *
339                  * The return will be zero for non sequence types.
340                  *
341                  * @see getBaseTypeId
342                  */
343                 static size_t getDepth(const Type& t) BOOST_NOEXCEPT;
344
345                 /**
346                  * Factory method to create Type instance from T.
347                  *
348                  * @return An instance that has TypeId for T.
349                  *
350                  * @note T must be supported by Value. Otherwise, it won't compile.
351                  *
352                  * @see is_supported_type
353                  */
354                 template < typename T >
355                 constexpr static Type typeOf(const T&) BOOST_NOEXCEPT
356                 {
357                     return Type{ IndexOfType< T >::value };
358                 }
359
360                 /**
361                  * Factory method to create Type instance from T.
362                  *
363                  * @return An instance that has TypeId for T.
364                  *
365                  * @note T must be supported by Value. Otherwise, it won't compile.
366                  *
367                  * @see is_supported_type
368                  */
369                 template < typename T >
370                 constexpr static Type typeOf() BOOST_NOEXCEPT
371                 {
372                     return Type{ IndexOfType< T >::value };
373                 }
374
375                 //! @cond
376                 friend bool operator==(const Type&, const Type&) BOOST_NOEXCEPT;
377                 //! @endcond
378
379             private:
380                 constexpr explicit Type(int which) BOOST_NOEXCEPT :
381                     m_which{ which }
382                 {
383                 }
384
385             private:
386                 int m_which;
387             };
388
389             /**
390              * Value holds a value among various types at a time.
391              *
392              * Type helps identify type information of Value.
393              *
394              * Supported types are below
395              * @code
396                 int
397                 double
398                 bool
399                 std::string
400                 RCSByteString
401                 RCSResourceAttributes
402
403                 std::vector< int >
404                 std::vector< double >
405                 std::vector< bool >
406                 std::vector< std::string >
407                 std::vector< RCSByteString >
408                 std::vector< RCSResourceAttributes >
409
410                 std::vector< std::vector< int > >
411                 std::vector< std::vector< std::vector< int > > >
412
413                 std::vector< std::vector< double > >
414                 std::vector< std::vector< std::vector< double > > >
415
416                 std::vector< std::vector< bool > >
417                 std::vector< std::vector< std::vector< bool > > >
418
419                 std::vector< std::vector< std::string > >
420                 std::vector< std::vector< std::vector< std::string > > >
421
422                 std::vector< std::vector< RCSByteString > >
423                 std::vector< std::vector< std::vector< RCSByteString > > >
424
425                 std::vector< std::vector< RCSResourceAttributes > >
426                 std::vector< std::vector< std::vector< RCSResourceAttributes > > >
427              * @endcode
428              *
429              * @see RCSResourceAttributes
430              * @see Type
431              * @see is_supported_type
432              */
433             class Value
434             {
435             public:
436                 class ComparisonHelper;
437
438                 Value();
439                 Value(const Value&);
440                 Value(Value&&) BOOST_NOEXCEPT;
441
442                 /**
443                  * Constructs a Value if T is a supported type.<br/>
444                  *       Otherwise it won't compile.
445                  */
446                 template< typename T, typename = typename enable_if_supported< T >::type >
447                 Value(T&& value) :
448                         m_data{ new ValueVariant{ std::forward< T >(value) } }
449                 {
450                 }
451
452                 Value(const char*);
453
454                 Value& operator=(const Value&);
455                 Value& operator=(Value&&);
456
457                 template< typename T, typename = typename enable_if_supported< T >::type >
458                 Value& operator=(T&& rhs)
459                 {
460                     *m_data = std::forward< T >(rhs);
461                     return *this;
462                 }
463
464                 Value& operator=(const char*);
465                 Value& operator=(std::nullptr_t);
466
467                 /**
468                  * Returns the underlying value as T.
469                  *
470                  * @return const reference to the underlying value.
471                  *
472                  * @throws BadGetException If type of the underlying value is not T.
473                  */
474                 template< typename T >
475                 typename std::add_lvalue_reference< const T >::type get() const
476                 {
477                     return checkedGet< T >();
478                 }
479
480                 /**
481                  * Returns the underlying value as T.
482                  *
483                  * @return reference to the underlying value.
484                  *
485                  * @throws BadGetException If type of the underlying value is not T.
486                  */
487                 template< typename T >
488                 typename std::add_lvalue_reference< T >::type get()
489                 {
490                     return checkedGet< T >();
491                 }
492
493                 /**
494                  * Returns Type information.
495                  *
496                  * @see Type
497                  */
498                 Type getType() const;
499
500                 /**
501                  * Returns a string representation.
502                  *
503                  */
504                 std::string toString() const;
505
506                 /**
507                  * Exchanges the content of the object by the content of the parameter.
508                  */
509                 void swap(Value&) BOOST_NOEXCEPT;
510
511                 //! @cond
512                 friend class RCSResourceAttributes;
513                 //! @endcond
514
515             private:
516                 template< typename T, typename = typename enable_if_supported< T >::type >
517                 typename std::add_lvalue_reference< T >::type checkedGet() const
518                 {
519                     try
520                     {
521                         return boost::get< T >(*m_data);
522                     }
523                     catch (const boost::bad_get&)
524                     {
525                         throw RCSBadGetException{ "Wrong type" };
526                     }
527                 }
528
529                 template< typename T, typename U >
530                 bool equals(const U& rhs) const
531                 {
532                     try
533                     {
534                         return get< T >() == rhs;
535                     }
536                     catch (const RCSBadGetException&)
537                     {
538                         return false;
539                     }
540                 }
541
542             private:
543                 boost::scoped_ptr< ValueVariant > m_data;
544             };
545
546             class KeyValuePair;
547             class iterator;
548             class const_iterator;
549
550         public:
551             RCSResourceAttributes() = default;
552             RCSResourceAttributes(const RCSResourceAttributes&) = default;
553             RCSResourceAttributes(RCSResourceAttributes&&) = default;
554
555             RCSResourceAttributes& operator=(const RCSResourceAttributes&) = default;
556             RCSResourceAttributes& operator=(RCSResourceAttributes&&) = default;
557
558             /**
559              * Returns an {@link iterator} referring to the first element.
560              */
561             iterator begin() BOOST_NOEXCEPT;
562
563             /**
564              * Returns an {@link iterator} referring to the <i>past-the-end element</i>.
565              */
566             iterator end() BOOST_NOEXCEPT;
567
568             /**
569              * @copydoc cbegin()
570              */
571             const_iterator begin() const BOOST_NOEXCEPT;
572
573             /**
574              * @copydoc cend()
575              */
576             const_iterator end() const BOOST_NOEXCEPT;
577
578             /**
579              * Returns a const_iterator referring to the first element.
580              */
581             const_iterator cbegin() const BOOST_NOEXCEPT;
582
583             /**
584              * Returns a const_iterator referring to the <i>past-the-end element</i>.
585              */
586             const_iterator cend() const BOOST_NOEXCEPT;
587
588             /**
589              * Accesses a value.
590              *
591              * If @a key matches the key of a value,
592              * returns a reference to its mapped value. <br/>
593              * If @a key doesn't match the key of any value,
594              * inserts a new value with that key and returns a reference to it.
595              * The element is a Value that has null.
596              *
597              * @param key Key of the element whose mapped value is accessed.
598              *
599              * @return A reference to the mapped value with @a key.
600              *
601              * @see at
602              */
603             Value& operator[](const std::string& key);
604
605             /**
606              * Accesses a value.
607              *
608              * If @a key matches the key of a value,
609              * returns a reference to its mapped value. <br/>
610              * If @a key doesn't match the key of any value,
611              * inserts a new value with that key and returns a reference to it.
612              * The value has null.
613              *
614              * @param key Key of the element whose mapped value is accessed.
615              *        This is moved instead of copied when a new value is inserted.
616              *
617              * @return A reference to the mapped value with @a key.
618              *
619              * @see at
620              */
621             Value& operator[](std::string&& key);
622
623             /**
624              * Accesses a value.
625              *
626              * If @a key matches the key of a value,
627              * returns a reference to its mapped value. <br/>
628              * If @a key doesn't match the key of any value, throws InvalidKeyException.
629              *
630              * @param key Key of the element whose mapped value is accessed.
631              *
632              * @throws InvalidKeyException If @a key doesn't match the key of any value.
633              *
634              * @return A reference to the mapped value with @a key.
635              *
636              * @see operator[]
637              */
638             Value& at(const std::string& key);
639
640             /**
641               * Accesses a value.
642               *
643               * If @a key matches the key of a value,
644               * returns a reference to its mapped value. <br/>
645               * If @a key doesn't match the key of any value, throws InvalidKeyException.
646               *
647               * @param key Key of the element whose mapped value is accessed.
648               *
649               * @throws InvalidKeyException If @a key doesn't match the key of any value.
650               *
651               * @return A const reference to the mapped value with @a key.
652               *
653               * @see operator[]
654               */
655             const Value& at(const std::string& key) const;
656
657             /**
658              * Removes all elements.
659              */
660             void clear() BOOST_NOEXCEPT;
661
662             /**
663              * Removes a single element.
664              *
665              * @param key Key of the element to be removed.
666              *
667              * @return true if an element is erased, false otherwise.
668              */
669             bool erase(const std::string& key);
670
671             /**
672              * Removes a single element.
673              *
674              * @param pos Iterator to the element to remove.
675              *
676              * @return Iterator following the last removed element.
677              */
678             iterator erase(const_iterator pos);
679
680             /**
681              * Checks this contains an element for the specified key.
682              *
683              * @param key Key to check.
684              *
685              * @return true if an element exists, false otherwise.
686              */
687             bool contains(const std::string& key) const;
688
689             /**
690              * Returns whether it is empty.
691              *
692              * @see size
693              */
694             bool empty() const BOOST_NOEXCEPT;
695
696             /**
697              * Returns the number of elements.
698              *
699              * @see empty
700              */
701             size_t size() const BOOST_NOEXCEPT;
702
703         private:
704             template< typename VISITOR >
705             void visit(VISITOR& visitor) const
706             {
707                 KeyValueVisitorHelper< VISITOR > helper{ visitor };
708
709                 for (const auto& i : m_values)
710                 {
711                     boost::variant< const std::string& > key{ i.first };
712                     boost::apply_visitor(helper, key, *i.second.m_data);
713                 }
714             }
715
716             template< typename VISITOR >
717             void visitToMove(VISITOR& visitor)
718             {
719                 KeyValueVisitorHelper< VISITOR, std::true_type > helper{ visitor };
720
721                 for (auto& i : m_values)
722                 {
723                     boost::variant< const std::string& > key{ i.first };
724                     boost::apply_visitor(helper, key, *i.second.m_data);
725                 }
726             }
727
728         private:
729             std::unordered_map< std::string, Value > m_values;
730
731             //! @cond
732             friend class ResourceAttributesConverter;
733
734             friend bool operator==(const RCSResourceAttributes&, const RCSResourceAttributes&);
735             //! @endcond
736         };
737
738         /**
739          * A helper class to avoid obscure comparisons of values which are supported
740          * by RCSResourceAttributes::Value caused by implicitly converting a value
741          * to a RCSResourceAttributes::Value.
742          *
743          * @see Value
744          * @see RCSResourceAttributes
745          * @see is_supported_type
746          */
747         class RCSResourceAttributes::Value::ComparisonHelper
748         {
749         public:
750             ComparisonHelper(const Value&);
751
752             ComparisonHelper(const ComparisonHelper&) = delete;
753             ComparisonHelper& operator=(const ComparisonHelper&) = delete;
754
755             template< typename T >
756             typename std::enable_if< is_supported_type< T >::value, bool >::type equals(
757                     const T& v) const
758             {
759                 return m_valueRef.equals< T >(v);
760             }
761
762             bool equals(const std::string& v) const
763             {
764                 return m_valueRef.equals< std::string >(v);
765             }
766
767             bool operator==(const ComparisonHelper&) const;
768
769         private:
770             const Value& m_valueRef;
771         };
772
773         //! @cond
774         template< typename T >
775         struct RCSResourceAttributes::IsSupportedTypeHelper
776         {
777             typedef boost::mpl::contains< ValueVariant::types, typename std::decay< T >::type > type;
778         };
779
780         template < typename T >
781         struct RCSResourceAttributes::IndexOfType
782         {
783             static_assert(RCSResourceAttributes::is_supported_type< T >::value,
784                 "The type is not supported!");
785
786             typedef typename boost::mpl::find< ValueVariant::types, T >::type iter;
787             typedef typename boost::mpl::begin< ValueVariant::types >::type mpl_begin;
788
789             static constexpr int value = boost::mpl::distance< mpl_begin, iter >::value;
790         };
791
792         template < typename T > constexpr int RCSResourceAttributes::IndexOfType< T >::value;
793         //! @endcond
794
795         /**
796          * @relates RCSResourceAttributes::Type
797          *
798          * Checks if the objects are equal, that is, whether types are exactly same.
799          *
800          * @return true if the objects are equal, false otherwise.
801          */
802         bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
803                 BOOST_NOEXCEPT;
804
805         /**
806          * @relates RCSResourceAttributes::Type
807          *
808          * Checks if the objects are not equal, that is, whether types are not exactly same.
809          *
810          * @return true if the objects are not equal, false otherwise.
811          */
812         bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
813                 BOOST_NOEXCEPT;
814
815         /**
816          * @relates RCSResourceAttributes::Value
817          *
818          * Checks if the contents are equal, that is,
819          * whether types are matched and underlying values are equal.
820          *
821          * @return true if the contents are equal, false otherwise.
822          */
823         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper&,
824                 const RCSResourceAttributes::Value::ComparisonHelper&);
825
826         /**
827          * @relates RCSResourceAttributes::Value
828          *
829          * Checks if the contents are not equal, that is,
830          * whether types are not matched or underlying values are not equal.
831          *
832          * @return true if the contents are not equal, false otherwise.
833          */
834         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper&,
835                 const RCSResourceAttributes::Value::ComparisonHelper&);
836
837         //! @cond
838         template< typename T >
839         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
840             std::is_constructible< std::string, T >::value, bool >::type
841         operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
842         {
843             return lhs.equals(rhs);
844         }
845
846         template< typename T >
847         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
848                     std::is_constructible< std::string, T >::value, bool >::type
849         operator==(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
850         {
851             return rhs == lhs;
852         }
853
854         template< typename T >
855         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
856                     std::is_constructible< std::string, T >::value, bool >::type
857         operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
858         {
859             return !(lhs == rhs);
860         }
861
862         template< typename T >
863         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
864                     std::is_constructible< std::string, T >::value, bool >::type
865         operator!=(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
866         {
867             return !(rhs == lhs);
868         }
869         //! @endcond
870
871         /**
872           * @relates RCSResourceAttributes
873           *
874           * Checks if the attributes are equal, that is, whether contents are equal.
875           *
876           * @return true if the attributes are equal, false otherwise.
877           */
878         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs);
879
880         /**
881           * @relates RCSResourceAttributes
882           *
883           * Checks if the attributes are not equal, that is, whether contents are not equal.
884           *
885           * @return true if the attributes are not equal, false otherwise.
886           */
887         bool operator!=(const RCSResourceAttributes&, const RCSResourceAttributes&);
888
889         /**
890          * KeyValuePair is a class to access attribute's key and value of an element pointed by
891          * iterators of RCSResourceAttributes.
892          *
893          *
894          * @see RCSResourceAttributes
895          * @see iterator
896          * @see const_iterator
897          */
898         class RCSResourceAttributes::KeyValuePair
899         {
900         private:
901             class KeyVisitor: public boost::static_visitor< const std::string& >
902             {
903             public:
904                 result_type operator()(iterator*) const BOOST_NOEXCEPT;
905                 result_type operator()(const_iterator*) const BOOST_NOEXCEPT;
906             };
907
908             class ValueVisitor: public boost::static_visitor< Value& >
909             {
910             public:
911                 result_type operator()(iterator*) BOOST_NOEXCEPT;
912                 result_type operator()(const_iterator*);
913             };
914
915             class ConstValueVisitor: public boost::static_visitor< const Value& >
916             {
917             public:
918                 result_type operator()(iterator*) const BOOST_NOEXCEPT;
919                 result_type operator()(const_iterator*) const BOOST_NOEXCEPT;
920             };
921
922         public:
923             const std::string& key() const BOOST_NOEXCEPT;
924             const RCSResourceAttributes::Value& value() const BOOST_NOEXCEPT;
925             RCSResourceAttributes::Value& value();
926
927         private:
928             KeyValuePair(const KeyValuePair&) = default;
929             KeyValuePair(boost::variant< iterator*, const_iterator* >&&) BOOST_NOEXCEPT;
930
931             KeyValuePair& operator=(const KeyValuePair&) = default;
932
933         private:
934             boost::variant< iterator*, const_iterator* > m_iterRef;
935
936             KeyVisitor m_keyVisitor;
937             ValueVisitor m_valueVisitor;
938             ConstValueVisitor m_constValueVisitor;
939
940             //! @cond
941             friend class iterator;
942             friend class const_iterator;
943             //! @endcond
944         };
945
946         /**
947          * A forward iterator to KeyValuePair.
948          *
949          * @see RCSResourceAttributes
950          * @see KeyValuePair
951          * @see const_iterator
952          */
953         class RCSResourceAttributes::iterator:
954                 public std::iterator< std::forward_iterator_tag, RCSResourceAttributes::KeyValuePair >
955         {
956         private:
957             typedef std::unordered_map< std::string, Value >::iterator base_iterator;
958
959         public:
960             iterator();
961             iterator(const iterator&);
962
963             iterator& operator=(const iterator&);
964
965             reference operator*();
966             pointer operator->();
967
968             iterator& operator++();
969             iterator operator++(int);
970
971             bool operator==(const iterator&) const;
972             bool operator!=(const iterator&) const;
973
974         private:
975             explicit iterator(base_iterator&&);
976
977         private:
978             base_iterator m_cur;
979             RCSResourceAttributes::KeyValuePair m_keyValuePair;
980
981             //! @cond
982             friend class RCSResourceAttributes;
983             //! @endcond
984         };
985
986
987         /**
988          * A forward iterator to const KeyValuePair.
989          *
990          * @see RCSResourceAttributes
991          * @see KeyValuePair
992          * @see iterator
993          */
994         class RCSResourceAttributes::const_iterator:
995                 public std::iterator< std::forward_iterator_tag,
996                                        const RCSResourceAttributes::KeyValuePair >
997         {
998         private:
999             typedef std::unordered_map< std::string, Value >::const_iterator base_iterator;
1000
1001         public:
1002             const_iterator();
1003             const_iterator(const const_iterator&);
1004             const_iterator(const RCSResourceAttributes::iterator&);
1005
1006             const_iterator& operator=(const const_iterator&);
1007             const_iterator& operator=(const RCSResourceAttributes::iterator&);
1008
1009             reference operator*() const;
1010             pointer operator->() const;
1011
1012             const_iterator& operator++();
1013             const_iterator operator++(int);
1014
1015             bool operator==(const const_iterator&) const;
1016             bool operator!=(const const_iterator&) const;
1017
1018         private:
1019             explicit const_iterator(base_iterator&&);
1020
1021         private:
1022             base_iterator m_cur;
1023             RCSResourceAttributes::KeyValuePair m_keyValuePair;
1024
1025             //! @cond
1026             friend class RCSResourceAttributes;
1027             //! @endcond
1028         };
1029
1030     }
1031 }
1032
1033 #endif // RES_ENCAPSULATION_RESOURCEATTRIBUTES_H