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