1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "RCSResourceAttributes.h"
25 #include "ResourceAttributesUtils.h"
26 #include "ResourceAttributesConverter.h"
28 #include "boost/lexical_cast.hpp"
29 #include "boost/mpl/advance.hpp"
30 #include "boost/mpl/size.hpp"
31 #include "boost/mpl/deref.hpp"
36 using namespace OIC::Service;
38 class ToStringVisitor: public boost::static_visitor<>
41 ToStringVisitor() = default;
42 ToStringVisitor(const ToStringVisitor&) = delete;
43 ToStringVisitor(ToStringVisitor&&) = delete;
45 ToStringVisitor& operator=(const ToStringVisitor&) = delete;
46 ToStringVisitor& operator=(ToStringVisitor&&) = delete;
48 template< typename T >
49 void operator()(const T& value)
51 m_stream << boost::lexical_cast< std::string >(value);
54 template< typename T >
55 void operator()(const std::vector< T >& v)
58 for (auto it = v.begin(); it != v.end(); ++it)
60 if (it != v.begin()) m_stream << ", ";
66 void operator()(std::nullptr_t)
71 void operator()(bool value)
73 m_stream << (value ? "true" : "false");
76 void operator()(const std::string& value)
78 m_stream << "\"" + value + "\"";
81 void operator()(const RCSByteString& value)
83 for (size_t i = 0; i < value.size(); ++i)
85 m_stream << "\\x" << std::hex << (int)value[i];
89 void operator()(const RCSResourceAttributes& attrs)
92 for (auto it = attrs.begin(); it != attrs.end(); ++it)
94 if (it != attrs.begin()) m_stream << ", ";
95 m_stream << "\"" << it->key() << "\" : " << it->value().toString();
100 std::string get() const {
101 return m_stream.str();
105 std::ostringstream m_stream;
108 class TypeVisitor: public boost::static_visitor< RCSResourceAttributes::Type >
111 TypeVisitor() = default;
112 TypeVisitor(const TypeVisitor&) = delete;
113 TypeVisitor(TypeVisitor&&) = delete;
115 TypeVisitor& operator=(const TypeVisitor&) = delete;
116 TypeVisitor& operator=(TypeVisitor&&) = delete;
118 template< typename T >
119 RCSResourceAttributes::Type operator()(const T& value) const
121 return RCSResourceAttributes::Type::typeOf(value);
129 template< typename T >
130 struct TypeInfoConverter;
133 struct TypeInfoConverter< int >
135 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::INT;
139 struct TypeInfoConverter< std::nullptr_t >
141 static constexpr RCSResourceAttributes::TypeId typeId =
142 RCSResourceAttributes::TypeId::NULL_T;
146 struct TypeInfoConverter< double >
148 static constexpr RCSResourceAttributes::TypeId typeId =
149 RCSResourceAttributes::TypeId::DOUBLE;
153 struct TypeInfoConverter< bool >
155 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::BOOL;
159 struct TypeInfoConverter< std::string >
161 static constexpr RCSResourceAttributes::TypeId typeId =
162 RCSResourceAttributes::TypeId::STRING;
166 struct TypeInfoConverter< RCSByteString >
168 static constexpr RCSResourceAttributes::TypeId typeId =
169 RCSResourceAttributes::TypeId::BYTESTRING;
173 struct TypeInfoConverter< RCSResourceAttributes >
175 static constexpr RCSResourceAttributes::TypeId typeId =
176 RCSResourceAttributes::TypeId::ATTRIBUTES;
179 template< typename T >
180 struct TypeInfoConverter< std::vector< T > >
182 static constexpr RCSResourceAttributes::TypeId typeId =
183 RCSResourceAttributes::TypeId::VECTOR;
186 template< typename T >
187 struct SequenceTraits
189 static constexpr size_t depth = 0;
193 template< typename T >
194 struct SequenceTraits< std::vector< T > >
196 static constexpr size_t depth = SequenceTraits< T >::depth + 1;
197 typedef typename SequenceTraits< T >::base_type base_type;
202 RCSResourceAttributes::TypeId m_typeId;
203 RCSResourceAttributes::Type m_baseType;
206 template< typename T, typename ST = SequenceTraits < T > >
207 constexpr static TypeInfo get()
209 return { TypeInfoConverter< T >::typeId ,
210 RCSResourceAttributes::Type::typeOf< typename ST::base_type >(), ST::depth };
213 template< typename VARIANT, int POS >
214 constexpr static TypeInfo get()
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;
219 return get< typename boost::mpl::deref< iter >::type >();
223 template< typename VARIANT, int POS >
224 inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept
226 auto vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
227 vec.push_back(TypeInfo::get< VARIANT, POS >());
231 template< typename VARIANT >
232 inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept
234 return { TypeInfo::get< VARIANT, 0 >() };
237 template< typename VARIANT >
238 inline TypeInfo getTypeInfo(int which) noexcept
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 >{ });
245 static_assert(variantSize > 0, "Variant has no type!");
247 return typeInfos[which];
249 } // unnamed namespace
256 RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
261 bool RCSResourceAttributes::Value::ComparisonHelper::operator==
262 (const Value::ComparisonHelper& rhs) const
264 return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
267 bool operator==(const RCSResourceAttributes::Type& lhs,
268 const RCSResourceAttributes::Type& rhs) noexcept
270 return lhs.m_which == rhs.m_which;
273 bool operator!=(const RCSResourceAttributes::Type& lhs,
274 const RCSResourceAttributes::Type& rhs) noexcept
276 return !(lhs == rhs);
279 bool operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
280 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
282 return lhs.operator==(rhs);
285 bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
286 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
288 return !lhs.operator==(rhs);
291 bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
293 return lhs.m_values == rhs.m_values;
296 bool operator!=(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
298 return !(lhs == rhs);
301 auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId
303 return ::getTypeInfo< ValueVariant >(m_which).m_typeId;
306 auto RCSResourceAttributes::Type::getBaseTypeId(const Type& t) noexcept -> TypeId
308 return ::getTypeInfo< ValueVariant >(t.m_which).m_baseType.getId();
311 size_t RCSResourceAttributes::Type::getDepth(const Type& t) noexcept
313 return ::getTypeInfo< ValueVariant >(t.m_which).m_depth;
317 RCSResourceAttributes::Value::Value() :
318 m_data{ new ValueVariant{} }
322 RCSResourceAttributes::Value::Value(const Value& from) :
323 m_data{ new ValueVariant{ *from.m_data } }
327 RCSResourceAttributes::Value::Value(Value&& from) noexcept :
328 m_data{ new ValueVariant{} }
330 m_data.swap(from.m_data);
333 RCSResourceAttributes::Value::Value(const char* value) :
334 m_data{ new ValueVariant{ std::string{ value } } }
338 auto RCSResourceAttributes::Value::operator=(const Value& rhs) -> Value&
340 *m_data = *rhs.m_data;
344 auto RCSResourceAttributes::Value::operator=(Value&& rhs) -> Value&
346 *m_data = ValueVariant{};
347 m_data->swap(*rhs.m_data);
351 auto RCSResourceAttributes::Value::operator=(const char* rhs) -> Value&
353 *m_data = std::string{ rhs };
357 auto RCSResourceAttributes::Value::operator=(std::nullptr_t) -> Value&
363 auto RCSResourceAttributes::Value::getType() const -> Type
365 return boost::apply_visitor(TypeVisitor(), *m_data);
368 std::string RCSResourceAttributes::Value::toString() const
370 ToStringVisitor visitor;
371 boost::apply_visitor(visitor, *m_data);
372 return visitor.get();
375 void RCSResourceAttributes::Value::swap(Value& rhs) noexcept
377 m_data.swap(rhs.m_data);
380 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
381 iterator* iter) const noexcept -> result_type
383 return iter->m_cur->first;
386 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
387 const_iterator* iter) const noexcept -> result_type
389 return iter->m_cur->first;
392 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept
395 return iter->m_cur->second;
398 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (const_iterator*)
401 // should not reach here.
402 throw RCSBadGetException("");
405 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
406 iterator*iter) const noexcept -> result_type
408 return iter->m_cur->second;
411 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
412 const_iterator* iter) const noexcept -> result_type
414 return iter->m_cur->second;
417 auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string&
419 return boost::apply_visitor(m_keyVisitor, m_iterRef);
422 auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value&
424 return boost::apply_visitor(m_constValueVisitor, m_iterRef);
427 auto RCSResourceAttributes::KeyValuePair::value() -> Value&
429 return boost::apply_visitor(m_valueVisitor, m_iterRef);
432 RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
433 const_iterator*>&& ref) noexcept :
439 RCSResourceAttributes::iterator::iterator() :
440 m_cur{ base_iterator{ } },
441 m_keyValuePair{ this }
445 RCSResourceAttributes::iterator::iterator(const iterator& rhs) :
447 m_keyValuePair{ this }
451 auto RCSResourceAttributes::iterator::operator=(const iterator& rhs) -> iterator&
457 RCSResourceAttributes::iterator::iterator(base_iterator&& iter) :
458 m_cur{ std::move(iter) },
459 m_keyValuePair{ this }
463 auto RCSResourceAttributes::iterator::operator*() -> KeyValuePair&
465 return m_keyValuePair;
468 auto RCSResourceAttributes::iterator::iterator::operator->() -> KeyValuePair*
470 return &m_keyValuePair;
473 auto RCSResourceAttributes::iterator::operator++() -> iterator&
479 auto RCSResourceAttributes::iterator::operator++(int) -> iterator
481 iterator iter(*this);
486 bool RCSResourceAttributes::iterator::operator==(const iterator& rhs) const
488 return m_cur == rhs.m_cur;
491 bool RCSResourceAttributes::iterator::operator!=(const iterator& rhs) const
493 return !(*this == rhs);
497 RCSResourceAttributes::const_iterator::const_iterator() :
498 m_cur{ base_iterator{} }, m_keyValuePair{ this }
502 RCSResourceAttributes::const_iterator::const_iterator(base_iterator&& iter) :
503 m_cur{ iter }, m_keyValuePair{ this }
507 RCSResourceAttributes::const_iterator::const_iterator(const const_iterator& rhs) :
508 m_cur{ rhs.m_cur }, m_keyValuePair{ this }
512 RCSResourceAttributes::const_iterator::const_iterator(
513 const RCSResourceAttributes::iterator& iter) :
514 m_cur{ iter.m_cur }, m_keyValuePair{ this }
518 auto RCSResourceAttributes::const_iterator::operator=(
519 const const_iterator& rhs) -> const_iterator&
525 auto RCSResourceAttributes::const_iterator::operator=(
526 const RCSResourceAttributes::iterator& iter) -> const_iterator&
532 auto RCSResourceAttributes::const_iterator::operator*() const -> reference
534 return m_keyValuePair;
537 auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
539 return &m_keyValuePair;
542 auto RCSResourceAttributes::const_iterator::operator++() -> const_iterator&
548 auto RCSResourceAttributes::const_iterator::operator++(int) -> const_iterator
550 const_iterator iter(*this);
555 bool RCSResourceAttributes::const_iterator::operator==(const const_iterator& rhs) const
557 return m_cur == rhs.m_cur;
560 bool RCSResourceAttributes::const_iterator::operator!=(const const_iterator& rhs) const
562 return !(*this == rhs);
566 auto RCSResourceAttributes::begin() noexcept -> iterator
568 return iterator{ m_values.begin() };
571 auto RCSResourceAttributes::end() noexcept -> iterator
573 return iterator{ m_values.end() };
576 auto RCSResourceAttributes::begin() const noexcept -> const_iterator
578 return const_iterator{ m_values.begin() };
581 auto RCSResourceAttributes::end() const noexcept -> const_iterator
583 return const_iterator{ m_values.end() };
586 auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator
588 return const_iterator{ m_values.begin() };
591 auto RCSResourceAttributes::cend() const noexcept -> const_iterator
593 return const_iterator{ m_values.end() };
596 auto RCSResourceAttributes::operator[](const std::string& key) -> Value&
598 return m_values[key];
601 auto RCSResourceAttributes::operator[](std::string&& key) -> Value&
603 return m_values[std::move(key)];
606 auto RCSResourceAttributes::at(const std::string& key) -> Value&
610 return m_values.at(key);
612 catch (const std::out_of_range&)
614 throw RCSInvalidKeyException{ "No attribute named '" + key + "'" };
618 auto RCSResourceAttributes::at(const std::string& key) const -> const Value&
622 return m_values.at(key);
624 catch (const std::out_of_range&)
626 throw RCSInvalidKeyException{ "No attribute named '" + key + "'" };
630 void RCSResourceAttributes::clear() noexcept
632 return m_values.clear();
635 bool RCSResourceAttributes::erase(const std::string& key)
637 return m_values.erase(key) == 1U;
640 auto RCSResourceAttributes::erase(const_iterator pos) -> iterator
642 return iterator{ m_values.erase(pos.m_cur) };
645 bool RCSResourceAttributes::contains(const std::string& key) const
647 return m_values.find(key) != m_values.end();
650 bool RCSResourceAttributes::empty() const noexcept
652 return m_values.empty();
655 size_t RCSResourceAttributes::size() const noexcept
657 return m_values.size();
661 bool acceptableAttributeValue(const RCSResourceAttributes::Value& dest,
662 const RCSResourceAttributes::Value& value)
664 if (dest.getType() != value.getType())
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 >()))
681 bool acceptableAttributes(const RCSResourceAttributes& dest, const RCSResourceAttributes& attr)
683 for (const auto& kv : attr)
685 if (!dest.contains(kv.key()))
690 if (!acceptableAttributeValue(dest.at(kv.key()), kv.value()))
699 AttrKeyValuePairs replaceAttributes(RCSResourceAttributes& dest,
700 const RCSResourceAttributes& newAttrs)
702 AttrKeyValuePairs replacedList;
704 for (const auto& kv : newAttrs)
706 if (dest[kv.key()] != kv.value())
708 RCSResourceAttributes::Value replacedValue;
709 replacedValue.swap(dest[kv.key()]);
710 dest[kv.key()] = kv.value();
712 replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) });