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 std::string operator()(std::nullptr_t) const
57 std::string operator()(bool value) const
59 return value ? "true" : "false";
62 std::string operator()(const std::string& value) const
67 std::string operator()(const OIC::Service::RCSResourceAttributes&) const
73 class TypeVisitor: public boost::static_visitor< RCSResourceAttributes::Type >
76 TypeVisitor() = default;
77 TypeVisitor(const TypeVisitor&) = delete;
78 TypeVisitor(TypeVisitor&&) = delete;
80 TypeVisitor& operator=(const TypeVisitor&) = delete;
81 TypeVisitor& operator=(TypeVisitor&&) = delete;
83 template< typename T >
84 RCSResourceAttributes::Type operator()(const T& value) const
86 return RCSResourceAttributes::Type::typeOf(value);
94 template< typename T >
95 struct TypeInfoConverter;
98 struct TypeInfoConverter< int >
100 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::INT;
104 struct TypeInfoConverter< std::nullptr_t >
106 static constexpr RCSResourceAttributes::TypeId typeId =
107 RCSResourceAttributes::TypeId::NULL_T;
111 struct TypeInfoConverter< double >
113 static constexpr RCSResourceAttributes::TypeId typeId =
114 RCSResourceAttributes::TypeId::DOUBLE;
118 struct TypeInfoConverter< bool >
120 static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::BOOL;
124 struct TypeInfoConverter< std::string >
126 static constexpr RCSResourceAttributes::TypeId typeId =
127 RCSResourceAttributes::TypeId::STRING;
131 struct TypeInfoConverter< RCSResourceAttributes >
133 static constexpr RCSResourceAttributes::TypeId typeId =
134 RCSResourceAttributes::TypeId::ATTRIBUTES;
139 RCSResourceAttributes::TypeId typeId;
141 template< typename TRAIT >
142 constexpr TypeInfo(TRAIT) :
143 typeId{ TRAIT::typeId }
147 template< typename VARIANT, int POS >
148 static constexpr TypeInfo get()
150 return TypeInfo(TypeInfoConverter<
151 typename boost::mpl::deref<
152 typename boost::mpl::advance<
153 typename boost::mpl::begin< typename VARIANT::types>::type,
154 boost::mpl::int_< POS >
160 template< typename VARIANT, int POS >
161 constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept
163 auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
164 vec.push_back(TypeInfo::get< VARIANT, POS >());
168 template< typename VARIANT >
169 constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept
171 return { TypeInfo::get< VARIANT, 0 >() };
174 template< typename VARIANT >
175 inline TypeInfo getTypeInfo(int which) noexcept
177 static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1;
178 static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
179 Int2Type< variantEnd >{ });
181 return typeInfos[which];
184 } // unnamed namespace
192 RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
197 bool RCSResourceAttributes::Value::ComparisonHelper::operator==
198 (const Value::ComparisonHelper& rhs) const
200 return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
203 bool operator==(const RCSResourceAttributes::Type& lhs,
204 const RCSResourceAttributes::Type& rhs) noexcept
206 return lhs.m_which == rhs.m_which;
209 bool operator!=(const RCSResourceAttributes::Type& lhs,
210 const RCSResourceAttributes::Type& rhs) noexcept
212 return !(lhs == rhs);
215 bool operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
216 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
218 return lhs.operator==(rhs);
221 bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
222 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
224 return !lhs.operator==(rhs);
227 bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
229 return lhs.m_values == rhs.m_values;
232 bool operator!=(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
234 return !(lhs == rhs);
237 auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId
239 return ::getTypeInfo< ValueVariant >(m_which).typeId;
242 RCSResourceAttributes::Value::Value() :
243 m_data{ new ValueVariant{} }
247 RCSResourceAttributes::Value::Value(const Value& from) :
248 m_data{ new ValueVariant{ *from.m_data } }
252 RCSResourceAttributes::Value::Value(Value&& from) noexcept :
253 m_data{ new ValueVariant{} }
255 m_data.swap(from.m_data);
258 RCSResourceAttributes::Value::Value(const char* value) :
259 m_data{ new ValueVariant{ std::string{ value } } }
263 auto RCSResourceAttributes::Value::operator=(const Value& rhs) -> Value&
265 *m_data = *rhs.m_data;
269 auto RCSResourceAttributes::Value::operator=(Value&& rhs) -> Value&
271 *m_data = ValueVariant{};
272 m_data->swap(*rhs.m_data);
276 auto RCSResourceAttributes::Value::operator=(const char* rhs) -> Value&
278 *m_data = std::string{ rhs };
282 auto RCSResourceAttributes::Value::operator=(std::nullptr_t) -> Value&
288 auto RCSResourceAttributes::Value::getType() const -> Type
290 return boost::apply_visitor(TypeVisitor(), *m_data);
293 std::string RCSResourceAttributes::Value::toString() const
295 return boost::apply_visitor(ToStringVisitor(), *m_data);
298 void RCSResourceAttributes::Value::swap(Value& rhs) noexcept
300 m_data.swap(rhs.m_data);
303 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
304 iterator* iter) const noexcept -> result_type
306 return iter->m_cur->first;
309 auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
310 const_iterator* iter) const noexcept -> result_type
312 return iter->m_cur->first;
315 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept
318 return iter->m_cur->second;
321 auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (const_iterator*)
324 // should not reach here.
325 throw BadGetException("");
328 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
329 iterator*iter) const noexcept -> result_type
331 return iter->m_cur->second;
334 auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
335 const_iterator* iter) const noexcept -> result_type
337 return iter->m_cur->second;
340 auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string&
342 return boost::apply_visitor(m_keyVisitor, m_iterRef);
345 auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value&
347 return boost::apply_visitor(m_constValueVisitor, m_iterRef);
350 auto RCSResourceAttributes::KeyValuePair::value() -> Value&
352 return boost::apply_visitor(m_valueVisitor, m_iterRef);
355 RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
356 const_iterator*>&& ref) noexcept :
362 RCSResourceAttributes::iterator::iterator() :
363 m_cur{ base_iterator{ } },
364 m_keyValuePair{ this }
368 RCSResourceAttributes::iterator::iterator(base_iterator&& iter) :
369 m_cur{ std::move(iter) },
370 m_keyValuePair{ this }
374 auto RCSResourceAttributes::iterator::operator*() -> KeyValuePair&
376 return m_keyValuePair;
379 auto RCSResourceAttributes::iterator::iterator::operator->() -> KeyValuePair*
381 return &m_keyValuePair;
384 auto RCSResourceAttributes::iterator::operator++() -> iterator&
390 auto RCSResourceAttributes::iterator::operator++(int) -> iterator
392 iterator iter(*this);
397 bool RCSResourceAttributes::iterator::operator==(const iterator& rhs) const
399 return m_cur == rhs.m_cur;
402 bool RCSResourceAttributes::iterator::operator!=(const iterator& rhs) const
404 return !(*this == rhs);
408 RCSResourceAttributes::const_iterator::const_iterator() :
409 m_cur{ base_iterator{} }, m_keyValuePair{ this }
413 RCSResourceAttributes::const_iterator::const_iterator(base_iterator&& iter) :
414 m_cur{ iter }, m_keyValuePair{ this }
418 RCSResourceAttributes::const_iterator::const_iterator(
419 const RCSResourceAttributes::iterator& iter) :
420 m_cur{ iter.m_cur }, m_keyValuePair{ this }
424 auto RCSResourceAttributes::const_iterator::operator=(
425 const RCSResourceAttributes::iterator& iter) -> const_iterator&
431 auto RCSResourceAttributes::const_iterator::operator*() const -> reference
433 return m_keyValuePair;
436 auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
438 return &m_keyValuePair;
441 auto RCSResourceAttributes::const_iterator::operator++() -> const_iterator&
447 auto RCSResourceAttributes::const_iterator::operator++(int) -> const_iterator
449 const_iterator iter(*this);
454 bool RCSResourceAttributes::const_iterator::operator==(const const_iterator& rhs) const
456 return m_cur == rhs.m_cur;
459 bool RCSResourceAttributes::const_iterator::operator!=(const const_iterator& rhs) const
461 return !(*this == rhs);
465 auto RCSResourceAttributes::begin() noexcept -> iterator
467 return iterator{ m_values.begin() };
470 auto RCSResourceAttributes::end() noexcept -> iterator
472 return iterator{ m_values.end() };
475 auto RCSResourceAttributes::begin() const noexcept -> const_iterator
477 return const_iterator{ m_values.begin() };
480 auto RCSResourceAttributes::end() const noexcept -> const_iterator
482 return const_iterator{ m_values.end() };
485 auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator
487 return const_iterator{ m_values.begin() };
490 auto RCSResourceAttributes::cend() const noexcept -> const_iterator
492 return const_iterator{ m_values.end() };
495 auto RCSResourceAttributes::operator[](const std::string& key) -> Value&
497 return m_values[key];
500 auto RCSResourceAttributes::operator[](std::string&& key) -> Value&
502 return m_values[std::move(key)];
505 auto RCSResourceAttributes::at(const std::string& key) -> Value&
509 return m_values.at(key);
511 catch (const std::out_of_range&)
513 throw InvalidKeyException{ "No attribute named '" + key + "'" };
517 auto RCSResourceAttributes::at(const std::string& key) const -> const Value&
521 return m_values.at(key);
523 catch (const std::out_of_range&)
525 throw InvalidKeyException{ "No attribute named '" + key + "'" };
529 void RCSResourceAttributes::clear() noexcept
531 return m_values.clear();
534 bool RCSResourceAttributes::erase(const std::string& key)
536 return m_values.erase(key) == 1U;
539 bool RCSResourceAttributes::contains(const std::string& key) const
541 return m_values.find(key) != m_values.end();
544 bool RCSResourceAttributes::empty() const noexcept
546 return m_values.empty();
549 size_t RCSResourceAttributes::size() const noexcept
551 return m_values.size();
555 bool acceptableAttributeValue(const RCSResourceAttributes::Value& dest,
556 const RCSResourceAttributes::Value& value)
558 if (dest.getType() != value.getType())
563 static_assert(RCSResourceAttributes::is_supported_type< RCSResourceAttributes >::value,
564 "RCSResourceAttributes doesn't have RCSResourceAttributes recursively.");
565 if (dest.getType().getId() == RCSResourceAttributes::TypeId::ATTRIBUTES
566 && !acceptableAttributes(dest.get< RCSResourceAttributes >(),
567 value.get< RCSResourceAttributes >()))
575 bool acceptableAttributes(const RCSResourceAttributes& dest, const RCSResourceAttributes& attr)
577 for (const auto& kv : attr)
579 if (!dest.contains(kv.key()))
584 if (!acceptableAttributeValue(dest.at(kv.key()), kv.value()))
593 AttrKeyValuePairs replaceAttributes(RCSResourceAttributes& dest,
594 const RCSResourceAttributes& newAttrs)
596 AttrKeyValuePairs replacedList;
598 for (const auto& kv : newAttrs)
600 if (dest[kv.key()] != kv.value())
602 RCSResourceAttributes::Value replacedValue;
603 replacedValue.swap(dest[kv.key()]);
604 dest[kv.key()] = kv.value();
606 replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) });