ee66c982b6d06e7c5c9f7b99a64220debc112234
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / common / primitiveResource / src / RCSResourceAttributes.cpp
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 #include "RCSResourceAttributes.h"
22
23 #include <sstream>
24
25 #include "ResourceAttributesUtils.h"
26 #include "ResourceAttributesConverter.h"
27
28 #include "boost/lexical_cast.hpp"
29 #include "boost/mpl/advance.hpp"
30 #include "boost/mpl/size.hpp"
31 #include "boost/mpl/deref.hpp"
32
33 #ifdef __APPLE__
34 #define OC_CONSTEXPR_INLINE inline
35 #else
36 #define OC_CONSTEXPR_INLINE constexpr inline
37 #endif
38
39 namespace
40 {
41
42     using namespace OIC::Service;
43
44     class ToStringVisitor: public boost::static_visitor<>
45     {
46     public:
47         ToStringVisitor() = default;
48         ToStringVisitor(const ToStringVisitor&) = delete;
49         ToStringVisitor(ToStringVisitor&&) = delete;
50
51         ToStringVisitor& operator=(const ToStringVisitor&) = delete;
52         ToStringVisitor& operator=(ToStringVisitor&&) = delete;
53
54         template< typename T >
55         void operator()(const T& value)
56         {
57             m_stream << boost::lexical_cast< std::string >(value);
58         }
59
60         template< typename T >
61         void operator()(const std::vector< T >& v)
62         {
63             m_stream << "[";
64             for (auto it = v.begin(); it != v.end(); ++it)
65             {
66                 if (it != v.begin()) m_stream << ", ";
67                 (*this)(*it);
68             }
69             m_stream << "]";
70         }
71
72         void operator()(std::nullptr_t)
73         {
74             m_stream << "";
75         }
76
77         void operator()(bool value)
78         {
79             m_stream << (value ? "true" : "false");
80         }
81
82         void operator()(const std::string& value)
83         {
84             m_stream << "\"" + value + "\"";
85         }
86
87         void operator()(const RCSResourceAttributes& attrs)
88         {
89             m_stream << "{";
90             for (auto it = attrs.begin(); it != attrs.end(); ++it)
91             {
92                 if (it != attrs.begin()) m_stream << ", ";
93                 m_stream << "\"" << it->key() << "\" : " << it->value().toString();
94             }
95             m_stream << "}";
96         }
97
98         std::string get() const {
99             return m_stream.str();
100         }
101
102     private:
103         std::ostringstream m_stream;
104     };
105
106     class TypeVisitor: public boost::static_visitor< RCSResourceAttributes::Type >
107     {
108     public:
109         TypeVisitor() = default;
110         TypeVisitor(const TypeVisitor&) = delete;
111         TypeVisitor(TypeVisitor&&) = delete;
112
113         TypeVisitor& operator=(const TypeVisitor&) = delete;
114         TypeVisitor& operator=(TypeVisitor&&) = delete;
115
116         template< typename T >
117         RCSResourceAttributes::Type operator()(const T& value) const
118         {
119             return RCSResourceAttributes::Type::typeOf(value);
120         }
121
122     };
123
124     template< int >
125     struct Int2Type {};
126
127     template< typename T >
128     struct TypeInfoConverter;
129
130     template< >
131     struct TypeInfoConverter< int >
132     {
133         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::INT;
134     };
135
136     template< >
137     struct TypeInfoConverter< std::nullptr_t >
138     {
139         static constexpr RCSResourceAttributes::TypeId typeId =
140                 RCSResourceAttributes::TypeId::NULL_T;
141     };
142
143     template< >
144     struct TypeInfoConverter< double >
145     {
146         static constexpr RCSResourceAttributes::TypeId typeId =
147                 RCSResourceAttributes::TypeId::DOUBLE;
148     };
149
150     template< >
151     struct TypeInfoConverter< bool >
152     {
153         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::BOOL;
154     };
155
156     template< >
157     struct TypeInfoConverter< std::string >
158     {
159         static constexpr RCSResourceAttributes::TypeId typeId =
160                 RCSResourceAttributes::TypeId::STRING;
161     };
162
163     template< >
164     struct TypeInfoConverter< RCSResourceAttributes >
165     {
166         static constexpr RCSResourceAttributes::TypeId typeId =
167                 RCSResourceAttributes::TypeId::ATTRIBUTES;
168     };
169
170     template< typename T >
171     struct TypeInfoConverter< std::vector< T > >
172     {
173         static constexpr RCSResourceAttributes::TypeId typeId =
174                 RCSResourceAttributes::TypeId::VECTOR;
175     };
176
177     template< typename T >
178     struct SequenceTraits
179     {
180         static constexpr size_t depth = 0;
181         typedef T base_type;
182     };
183
184     template< typename T >
185     struct SequenceTraits< std::vector< T > >
186     {
187         static constexpr size_t depth = SequenceTraits< T >::depth + 1;
188         typedef typename SequenceTraits< T >::base_type base_type;
189     };
190
191     struct TypeInfo
192     {
193         RCSResourceAttributes::TypeId m_typeId;
194         RCSResourceAttributes::Type m_baseType;
195         size_t m_depth;
196
197         template< typename T, typename ST = SequenceTraits < T > >
198         constexpr static TypeInfo get()
199         {
200             return { TypeInfoConverter< T >::typeId ,
201                     RCSResourceAttributes::Type::typeOf< typename ST::base_type >(), ST::depth };
202         }
203
204         template< typename VARIANT, int POS >
205         constexpr static TypeInfo get()
206         {
207             typedef typename boost::mpl::begin< typename VARIANT::types >::type mpl_begin;
208             typedef typename boost::mpl::advance< mpl_begin, boost::mpl::int_< POS > >::type iter;
209
210             return get< typename boost::mpl::deref< iter >::type >();
211         }
212     };
213
214     template< typename VARIANT, int POS >
215     OC_CONSTEXPR_INLINE std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept
216     {
217         auto vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
218         vec.push_back(TypeInfo::get< VARIANT, POS >());
219         return vec;
220     }
221
222     template< typename VARIANT >
223     OC_CONSTEXPR_INLINE std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept
224     {
225         return { TypeInfo::get< VARIANT, 0 >() };
226     }
227
228     template< typename VARIANT >
229     inline TypeInfo getTypeInfo(int which) noexcept
230     {
231         static constexpr size_t variantSize = boost::mpl::size< typename VARIANT::types >::value;
232         static constexpr size_t variantEnd = variantSize - 1;
233         static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
234                 Int2Type< variantEnd >{ });
235
236         static_assert(variantSize > 0, "Variant has no type!");
237
238         return typeInfos[which];
239     }
240
241 } // unnamed namespace
242
243
244 namespace OIC
245 {
246     namespace Service
247     {
248
249         RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
250                 m_valueRef(v)
251         {
252         }
253
254         bool RCSResourceAttributes::Value::ComparisonHelper::operator==
255                 (const Value::ComparisonHelper& rhs) const
256         {
257             return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
258         }
259
260         bool operator==(const RCSResourceAttributes::Type& lhs,
261                 const RCSResourceAttributes::Type& rhs) noexcept
262         {
263             return lhs.m_which == rhs.m_which;
264         }
265
266         bool operator!=(const RCSResourceAttributes::Type& lhs,
267                 const RCSResourceAttributes::Type& rhs) noexcept
268         {
269             return !(lhs == rhs);
270         }
271
272         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
273                 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
274         {
275             return lhs.operator==(rhs);
276         }
277
278         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
279                 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
280         {
281             return !lhs.operator==(rhs);
282         }
283
284         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
285         {
286             return lhs.m_values == rhs.m_values;
287         }
288
289         bool operator!=(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
290         {
291             return !(lhs == rhs);
292         }
293
294         auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId
295         {
296             return ::getTypeInfo< ValueVariant >(m_which).m_typeId;
297         }
298
299         auto RCSResourceAttributes::Type::getBaseTypeId(const Type& t) noexcept -> TypeId
300         {
301             return ::getTypeInfo< ValueVariant >(t.m_which).m_baseType.getId();
302         }
303
304         size_t RCSResourceAttributes::Type::getDepth(const Type& t) noexcept
305         {
306             return ::getTypeInfo< ValueVariant >(t.m_which).m_depth;
307         }
308
309
310         RCSResourceAttributes::Value::Value() :
311                 m_data{ new ValueVariant{} }
312         {
313         }
314
315         RCSResourceAttributes::Value::Value(const Value& from) :
316                 m_data{ new ValueVariant{ *from.m_data } }
317         {
318         }
319
320         RCSResourceAttributes::Value::Value(Value&& from) noexcept :
321                 m_data{ new ValueVariant{} }
322         {
323             m_data.swap(from.m_data);
324         }
325
326         RCSResourceAttributes::Value::Value(const char* value) :
327                 m_data{ new ValueVariant{ std::string{ value } } }
328         {
329         }
330
331         auto RCSResourceAttributes::Value::operator=(const Value& rhs) -> Value&
332         {
333             *m_data = *rhs.m_data;
334             return *this;
335         }
336
337         auto RCSResourceAttributes::Value::operator=(Value&& rhs) -> Value&
338         {
339             *m_data = ValueVariant{};
340             m_data->swap(*rhs.m_data);
341             return *this;
342         }
343
344         auto RCSResourceAttributes::Value::operator=(const char* rhs) -> Value&
345         {
346             *m_data = std::string{ rhs };
347             return *this;
348         }
349
350         auto RCSResourceAttributes::Value::operator=(std::nullptr_t) -> Value&
351         {
352             *m_data = nullptr;
353             return *this;
354         }
355
356         auto RCSResourceAttributes::Value::getType() const -> Type
357         {
358             return boost::apply_visitor(TypeVisitor(), *m_data);
359         }
360
361         std::string RCSResourceAttributes::Value::toString() const
362         {
363             ToStringVisitor visitor;
364             boost::apply_visitor(visitor, *m_data);
365             return visitor.get();
366         }
367
368         void RCSResourceAttributes::Value::swap(Value& rhs) noexcept
369         {
370             m_data.swap(rhs.m_data);
371         }
372
373         auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
374                 iterator* iter) const noexcept -> result_type
375         {
376             return iter->m_cur->first;
377         }
378
379         auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
380                 const_iterator* iter) const noexcept -> result_type
381         {
382             return iter->m_cur->first;
383         }
384
385         auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept
386                 -> result_type
387         {
388             return iter->m_cur->second;
389         }
390
391         auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (const_iterator*)
392                 -> result_type
393         {
394             // should not reach here.
395             throw RCSBadGetException("");
396         }
397
398         auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
399                 iterator*iter) const noexcept -> result_type
400         {
401             return iter->m_cur->second;
402         }
403
404         auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
405                 const_iterator* iter) const noexcept -> result_type
406         {
407             return iter->m_cur->second;
408         }
409
410         auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string&
411         {
412             return boost::apply_visitor(m_keyVisitor, m_iterRef);
413         }
414
415         auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value&
416         {
417             return boost::apply_visitor(m_constValueVisitor, m_iterRef);
418         }
419
420         auto RCSResourceAttributes::KeyValuePair::value() -> Value&
421         {
422             return boost::apply_visitor(m_valueVisitor, m_iterRef);
423         }
424
425         RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
426                 const_iterator*>&& ref) noexcept :
427                 m_iterRef{ ref }
428         {
429         }
430
431
432         RCSResourceAttributes::iterator::iterator() :
433                 m_cur{ base_iterator{ } },
434                 m_keyValuePair{ this }
435         {
436         }
437
438         RCSResourceAttributes::iterator::iterator(const iterator& rhs) :
439                 m_cur{ rhs.m_cur },
440                 m_keyValuePair{ this }
441         {
442         }
443
444         auto RCSResourceAttributes::iterator::operator=(const iterator& rhs) -> iterator&
445         {
446             m_cur = rhs.m_cur;
447             return *this;
448         }
449
450         RCSResourceAttributes::iterator::iterator(base_iterator&& iter) :
451                 m_cur{ std::move(iter) },
452                 m_keyValuePair{ this }
453         {
454         }
455
456         auto RCSResourceAttributes::iterator::operator*() -> KeyValuePair&
457         {
458             return m_keyValuePair;
459         }
460
461         auto RCSResourceAttributes::iterator::iterator::operator->() -> KeyValuePair*
462         {
463             return &m_keyValuePair;
464         }
465
466         auto RCSResourceAttributes::iterator::operator++() -> iterator&
467         {
468             ++m_cur;
469             return *this;
470         }
471
472         auto RCSResourceAttributes::iterator::operator++(int) -> iterator
473         {
474             iterator iter(*this);
475             ++(*this);
476             return iter;
477         }
478
479         bool RCSResourceAttributes::iterator::operator==(const iterator& rhs) const
480         {
481             return m_cur == rhs.m_cur;
482         }
483
484         bool RCSResourceAttributes::iterator::operator!=(const iterator& rhs) const
485         {
486             return !(*this == rhs);
487         }
488
489
490         RCSResourceAttributes::const_iterator::const_iterator() :
491                 m_cur{ base_iterator{} }, m_keyValuePair{ this }
492         {
493         }
494
495         RCSResourceAttributes::const_iterator::const_iterator(base_iterator&& iter) :
496                 m_cur{ iter }, m_keyValuePair{ this }
497         {
498         }
499
500         RCSResourceAttributes::const_iterator::const_iterator(const const_iterator& rhs) :
501                 m_cur{ rhs.m_cur }, m_keyValuePair{ this }
502         {
503         }
504
505         RCSResourceAttributes::const_iterator::const_iterator(
506                 const RCSResourceAttributes::iterator& iter) :
507                 m_cur{ iter.m_cur }, m_keyValuePair{ this }
508         {
509         }
510
511         auto RCSResourceAttributes::const_iterator::operator=(
512                 const const_iterator& rhs) -> const_iterator&
513         {
514             m_cur = rhs.m_cur;
515             return *this;
516         }
517
518         auto RCSResourceAttributes::const_iterator::operator=(
519                 const RCSResourceAttributes::iterator& iter) -> const_iterator&
520         {
521             m_cur = iter.m_cur;
522             return *this;
523         }
524
525         auto RCSResourceAttributes::const_iterator::operator*() const -> reference
526         {
527             return m_keyValuePair;
528         }
529
530         auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
531         {
532             return &m_keyValuePair;
533         }
534
535         auto RCSResourceAttributes::const_iterator::operator++() -> const_iterator&
536         {
537             ++m_cur;
538             return *this;
539         }
540
541         auto RCSResourceAttributes::const_iterator::operator++(int) -> const_iterator
542         {
543             const_iterator iter(*this);
544             ++(*this);
545             return iter;
546         }
547
548         bool RCSResourceAttributes::const_iterator::operator==(const const_iterator& rhs) const
549         {
550             return m_cur == rhs.m_cur;
551         }
552
553         bool RCSResourceAttributes::const_iterator::operator!=(const const_iterator& rhs) const
554         {
555             return !(*this == rhs);
556         }
557
558
559         auto RCSResourceAttributes::begin() noexcept -> iterator
560         {
561             return iterator{ m_values.begin() };
562         }
563
564         auto RCSResourceAttributes::end() noexcept -> iterator
565         {
566             return iterator{ m_values.end() };
567         }
568
569         auto RCSResourceAttributes::begin() const noexcept -> const_iterator
570         {
571             return const_iterator{ m_values.begin() };
572         }
573
574         auto RCSResourceAttributes::end() const noexcept -> const_iterator
575         {
576             return const_iterator{ m_values.end() };
577         }
578
579         auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator
580         {
581             return const_iterator{ m_values.begin() };
582         }
583
584         auto RCSResourceAttributes::cend() const noexcept -> const_iterator
585         {
586             return const_iterator{ m_values.end() };
587         }
588
589         auto RCSResourceAttributes::operator[](const std::string& key) -> Value&
590         {
591             return m_values[key];
592         }
593
594         auto RCSResourceAttributes::operator[](std::string&& key) -> Value&
595         {
596             return m_values[std::move(key)];
597         }
598
599         auto RCSResourceAttributes::at(const std::string& key) -> Value&
600         {
601             try
602             {
603                 return m_values.at(key);
604             }
605             catch (const std::out_of_range&)
606             {
607                 throw RCSInvalidKeyException{ "No attribute named '" + key + "'" };
608             }
609         }
610
611         auto RCSResourceAttributes::at(const std::string& key) const -> const Value&
612         {
613             try
614             {
615                 return m_values.at(key);
616             }
617             catch (const std::out_of_range&)
618             {
619                 throw RCSInvalidKeyException{ "No attribute named '" + key + "'" };
620             }
621         }
622
623         void RCSResourceAttributes::clear() noexcept
624         {
625             return m_values.clear();
626         }
627
628         bool RCSResourceAttributes::erase(const std::string& key)
629         {
630             return m_values.erase(key) == 1U;
631         }
632
633         auto RCSResourceAttributes::erase(const_iterator pos) -> iterator
634         {
635             return iterator{ m_values.erase(pos.m_cur) };
636         }
637
638         bool RCSResourceAttributes::contains(const std::string& key) const
639         {
640             return m_values.find(key) != m_values.end();
641         }
642
643         bool RCSResourceAttributes::empty() const noexcept
644         {
645             return m_values.empty();
646         }
647
648         size_t RCSResourceAttributes::size() const noexcept
649         {
650             return m_values.size();
651         }
652
653
654         bool acceptableAttributeValue(const RCSResourceAttributes::Value& dest,
655                 const RCSResourceAttributes::Value& value)
656         {
657             if (dest.getType() != value.getType())
658             {
659                 return false;
660             }
661
662             static_assert(RCSResourceAttributes::is_supported_type< RCSResourceAttributes >::value,
663                     "RCSResourceAttributes doesn't have RCSResourceAttributes recursively.");
664             if (dest.getType().getId() == RCSResourceAttributes::TypeId::ATTRIBUTES
665                     && !acceptableAttributes(dest.get< RCSResourceAttributes >(),
666                             value.get< RCSResourceAttributes >()))
667             {
668                 return false;
669             }
670
671             return true;
672         }
673
674         bool acceptableAttributes(const RCSResourceAttributes& dest, const RCSResourceAttributes& attr)
675         {
676             for (const auto& kv : attr)
677             {
678                 if (!dest.contains(kv.key()))
679                 {
680                     return false;
681                 }
682
683                 if (!acceptableAttributeValue(dest.at(kv.key()), kv.value()))
684                 {
685                     return false;
686                 }
687             }
688
689             return true;
690         }
691
692         AttrKeyValuePairs replaceAttributes(RCSResourceAttributes& dest,
693                 const RCSResourceAttributes& newAttrs)
694         {
695             AttrKeyValuePairs replacedList;
696
697             for (const auto& kv : newAttrs)
698             {
699                 if (dest[kv.key()] != kv.value())
700                 {
701                     RCSResourceAttributes::Value replacedValue;
702                     replacedValue.swap(dest[kv.key()]);
703                     dest[kv.key()] = kv.value();
704
705                     replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) });
706                 }
707             }
708
709             return replacedList;
710         }
711
712     }
713 }