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