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>
23 #include <ResourceAttributesUtils.h>
24 #include <ResourceAttributesConverter.h>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/mpl/advance.hpp>
28 #include <boost/mpl/size.hpp>
29 #include <boost/mpl/deref.hpp>
34 using namespace OIC::Service;
36 class ToStringVisitor: public boost::static_visitor< std::string >
39 ToStringVisitor() = default;
40 ToStringVisitor(const ToStringVisitor&) = delete;
41 ToStringVisitor(ToStringVisitor&&) = delete;
43 ToStringVisitor& operator=(const ToStringVisitor&) = delete;
44 ToStringVisitor& operator=(ToStringVisitor&&) = delete;
46 template < typename T >
47 std::string operator()(const T& value) const
49 return boost::lexical_cast<std::string>(value);
52 template< typename T >
53 std::string operator()(const std::vector< T >&) const
58 std::string operator()(std::nullptr_t) const
63 std::string operator()(bool value) const
65 return value ? "true" : "false";
68 std::string operator()(const std::string& value) const
73 std::string operator()(const OIC::Service::RCSResourceAttributes&) const
79 class TypeVisitor: public boost::static_visitor< RCSResourceAttributes::Type >
82 TypeVisitor() = default;
83 TypeVisitor(const TypeVisitor&) = delete;
84 TypeVisitor(TypeVisitor&&) = delete;
86 TypeVisitor& operator=(const TypeVisitor&) = delete;
87 TypeVisitor& operator=(TypeVisitor&&) = delete;
89 template< typename T >
90 RCSResourceAttributes::Type operator()(const T& value) const
92 return RCSResourceAttributes::Type::typeOf(value);
100 template< typename T >
101 struct TypeInfoConverter;
104 struct TypeInfoConverter< int >
106 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::INT;
110 struct TypeInfoConverter< std::nullptr_t >
112 static constexpr RCSResourceAttributes::TypeId typeId =
113 RCSResourceAttributes::TypeId::NULL_T;
117 struct TypeInfoConverter< double >
119 static constexpr RCSResourceAttributes::TypeId typeId =
120 RCSResourceAttributes::TypeId::DOUBLE;
124 struct TypeInfoConverter< bool >
126 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::BOOL;
130 struct TypeInfoConverter< std::string >
132 static constexpr RCSResourceAttributes::TypeId typeId =
133 RCSResourceAttributes::TypeId::STRING;
137 struct TypeInfoConverter< RCSResourceAttributes >
139 static constexpr RCSResourceAttributes::TypeId typeId =
140 RCSResourceAttributes::TypeId::ATTRIBUTES;
143 template< typename T >
144 struct TypeInfoConverter< std::vector< T > >
146 static constexpr RCSResourceAttributes::TypeId typeId =
147 RCSResourceAttributes::TypeId::VECTOR;
150 template< typename T >
151 struct SequenceTraits
153 static constexpr size_t depth = 0;
157 template< typename T >
158 struct SequenceTraits< std::vector< T > >
160 static constexpr size_t depth = SequenceTraits< T >::depth + 1;
161 typedef typename SequenceTraits< T >::base_type base_type;
166 RCSResourceAttributes::TypeId m_typeId;
167 RCSResourceAttributes::Type m_baseType;
170 template< typename T, typename ST = SequenceTraits < T > >
171 constexpr static TypeInfo get()
173 return { TypeInfoConverter< T >::typeId ,
174 RCSResourceAttributes::Type::typeOf< typename ST::base_type >(), ST::depth };
177 template< typename VARIANT, int POS >
178 constexpr static TypeInfo get()
180 typedef typename boost::mpl::begin< typename VARIANT::types >::type mpl_begin;
181 typedef typename boost::mpl::advance< mpl_begin, boost::mpl::int_< POS > >::type iter;
183 return get< typename boost::mpl::deref< iter >::type >();
187 template< typename VARIANT, int POS >
188 constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept
190 auto vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
191 vec.push_back(TypeInfo::get< VARIANT, POS >());
195 template< typename VARIANT >
196 constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept
198 return { TypeInfo::get< VARIANT, 0 >() };
201 template< typename VARIANT >
202 inline TypeInfo getTypeInfo(int which) noexcept
204 static constexpr size_t variantSize = boost::mpl::size< typename VARIANT::types >::value;
205 static constexpr size_t variantEnd = variantSize - 1;
206 static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
207 Int2Type< variantEnd >{ });
209 static_assert(variantSize > 0, "Variant has no type!");
211 return typeInfos[which];
214 } // unnamed namespace
222 RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
227 bool RCSResourceAttributes::Value::ComparisonHelper::operator==
228 (const Value::ComparisonHelper& rhs) const
230 return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
233 bool operator==(const RCSResourceAttributes::Type& lhs,
234 const RCSResourceAttributes::Type& rhs) noexcept
236 return lhs.m_which == rhs.m_which;
239 bool operator!=(const RCSResourceAttributes::Type& lhs,
240 const RCSResourceAttributes::Type& rhs) noexcept
242 return !(lhs == rhs);
245 bool operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
246 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
248 return lhs.operator==(rhs);
251 bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
252 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
254 return !lhs.operator==(rhs);
257 bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
259 return lhs.m_values == rhs.m_values;
262 bool operator!=(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
264 return !(lhs == rhs);
267 auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId
269 return ::getTypeInfo< ValueVariant >(m_which).m_typeId;
272 auto RCSResourceAttributes::Type::getBaseTypeId(const Type& t) noexcept -> TypeId
274 return ::getTypeInfo< ValueVariant >(t.m_which).m_baseType.getId();
277 size_t RCSResourceAttributes::Type::getDepth(const Type& t) noexcept
279 return ::getTypeInfo< ValueVariant >(t.m_which).m_depth;
283 RCSResourceAttributes::Value::Value() :
284 m_data{ new ValueVariant{} }
288 RCSResourceAttributes::Value::Value(const Value& from) :
289 m_data{ new ValueVariant{ *from.m_data } }
293 RCSResourceAttributes::Value::Value(Value&& from) noexcept :
294 m_data{ new ValueVariant{} }
296 m_data.swap(from.m_data);
299 RCSResourceAttributes::Value::Value(const char* value) :
300 m_data{ new ValueVariant{ std::string{ value } } }
304 auto RCSResourceAttributes::Value::operator=(const Value& rhs) -> Value&
306 *m_data = *rhs.m_data;
310 auto RCSResourceAttributes::Value::operator=(Value&& rhs) -> Value&
312 *m_data = ValueVariant{};
313 m_data->swap(*rhs.m_data);
317 auto RCSResourceAttributes::Value::operator=(const char* rhs) -> Value&
319 *m_data = std::string{ rhs };
323 auto RCSResourceAttributes::Value::operator=(std::nullptr_t) -> Value&
329 auto RCSResourceAttributes::Value::getType() const -> Type
331 return boost::apply_visitor(TypeVisitor(), *m_data);
334 std::string RCSResourceAttributes::Value::toString() const
336 return boost::apply_visitor(ToStringVisitor(), *m_data);
339 void RCSResourceAttributes::Value::swap(Value& rhs) noexcept
341 m_data.swap(rhs.m_data);
344 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
345 iterator* iter) const noexcept -> result_type
347 return iter->m_cur->first;
350 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
351 const_iterator* iter) const noexcept -> result_type
353 return iter->m_cur->first;
356 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept
359 return iter->m_cur->second;
362 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (const_iterator*)
365 // should not reach here.
366 throw BadGetException("");
369 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
370 iterator*iter) const noexcept -> result_type
372 return iter->m_cur->second;
375 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
376 const_iterator* iter) const noexcept -> result_type
378 return iter->m_cur->second;
381 auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string&
383 return boost::apply_visitor(m_keyVisitor, m_iterRef);
386 auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value&
388 return boost::apply_visitor(m_constValueVisitor, m_iterRef);
391 auto RCSResourceAttributes::KeyValuePair::value() -> Value&
393 return boost::apply_visitor(m_valueVisitor, m_iterRef);
396 RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
397 const_iterator*>&& ref) noexcept :
403 RCSResourceAttributes::iterator::iterator() :
404 m_cur{ base_iterator{ } },
405 m_keyValuePair{ this }
409 RCSResourceAttributes::iterator::iterator(base_iterator&& iter) :
410 m_cur{ std::move(iter) },
411 m_keyValuePair{ this }
415 auto RCSResourceAttributes::iterator::operator*() -> KeyValuePair&
417 return m_keyValuePair;
420 auto RCSResourceAttributes::iterator::iterator::operator->() -> KeyValuePair*
422 return &m_keyValuePair;
425 auto RCSResourceAttributes::iterator::operator++() -> iterator&
431 auto RCSResourceAttributes::iterator::operator++(int) -> iterator
433 iterator iter(*this);
438 bool RCSResourceAttributes::iterator::operator==(const iterator& rhs) const
440 return m_cur == rhs.m_cur;
443 bool RCSResourceAttributes::iterator::operator!=(const iterator& rhs) const
445 return !(*this == rhs);
449 RCSResourceAttributes::const_iterator::const_iterator() :
450 m_cur{ base_iterator{} }, m_keyValuePair{ this }
454 RCSResourceAttributes::const_iterator::const_iterator(base_iterator&& iter) :
455 m_cur{ iter }, m_keyValuePair{ this }
459 RCSResourceAttributes::const_iterator::const_iterator(
460 const RCSResourceAttributes::iterator& iter) :
461 m_cur{ iter.m_cur }, m_keyValuePair{ this }
465 auto RCSResourceAttributes::const_iterator::operator=(
466 const RCSResourceAttributes::iterator& iter) -> const_iterator&
472 auto RCSResourceAttributes::const_iterator::operator*() const -> reference
474 return m_keyValuePair;
477 auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
479 return &m_keyValuePair;
482 auto RCSResourceAttributes::const_iterator::operator++() -> const_iterator&
488 auto RCSResourceAttributes::const_iterator::operator++(int) -> const_iterator
490 const_iterator iter(*this);
495 bool RCSResourceAttributes::const_iterator::operator==(const const_iterator& rhs) const
497 return m_cur == rhs.m_cur;
500 bool RCSResourceAttributes::const_iterator::operator!=(const const_iterator& rhs) const
502 return !(*this == rhs);
506 auto RCSResourceAttributes::begin() noexcept -> iterator
508 return iterator{ m_values.begin() };
511 auto RCSResourceAttributes::end() noexcept -> iterator
513 return iterator{ m_values.end() };
516 auto RCSResourceAttributes::begin() const noexcept -> const_iterator
518 return const_iterator{ m_values.begin() };
521 auto RCSResourceAttributes::end() const noexcept -> const_iterator
523 return const_iterator{ m_values.end() };
526 auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator
528 return const_iterator{ m_values.begin() };
531 auto RCSResourceAttributes::cend() const noexcept -> const_iterator
533 return const_iterator{ m_values.end() };
536 auto RCSResourceAttributes::operator[](const std::string& key) -> Value&
538 return m_values[key];
541 auto RCSResourceAttributes::operator[](std::string&& key) -> Value&
543 return m_values[std::move(key)];
546 auto RCSResourceAttributes::at(const std::string& key) -> Value&
550 return m_values.at(key);
552 catch (const std::out_of_range&)
554 throw InvalidKeyException{ "No attribute named '" + key + "'" };
558 auto RCSResourceAttributes::at(const std::string& key) const -> const Value&
562 return m_values.at(key);
564 catch (const std::out_of_range&)
566 throw InvalidKeyException{ "No attribute named '" + key + "'" };
570 void RCSResourceAttributes::clear() noexcept
572 return m_values.clear();
575 bool RCSResourceAttributes::erase(const std::string& key)
577 return m_values.erase(key) == 1U;
580 bool RCSResourceAttributes::contains(const std::string& key) const
582 return m_values.find(key) != m_values.end();
585 bool RCSResourceAttributes::empty() const noexcept
587 return m_values.empty();
590 size_t RCSResourceAttributes::size() const noexcept
592 return m_values.size();
596 bool acceptableAttributeValue(const RCSResourceAttributes::Value& dest,
597 const RCSResourceAttributes::Value& value)
599 if (dest.getType() != value.getType())
604 static_assert(RCSResourceAttributes::is_supported_type< RCSResourceAttributes >::value,
605 "RCSResourceAttributes doesn't have RCSResourceAttributes recursively.");
606 if (dest.getType().getId() == RCSResourceAttributes::TypeId::ATTRIBUTES
607 && !acceptableAttributes(dest.get< RCSResourceAttributes >(),
608 value.get< RCSResourceAttributes >()))
616 bool acceptableAttributes(const RCSResourceAttributes& dest, const RCSResourceAttributes& attr)
618 for (const auto& kv : attr)
620 if (!dest.contains(kv.key()))
625 if (!acceptableAttributeValue(dest.at(kv.key()), kv.value()))
634 AttrKeyValuePairs replaceAttributes(RCSResourceAttributes& dest,
635 const RCSResourceAttributes& newAttrs)
637 AttrKeyValuePairs replacedList;
639 for (const auto& kv : newAttrs)
641 if (dest[kv.key()] != kv.value())
643 RCSResourceAttributes::Value replacedValue;
644 replacedValue.swap(dest[kv.key()]);
645 dest[kv.key()] = kv.value();
647 replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) });