Any.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. //
  2. // Any.h
  3. //
  4. // Library: Foundation
  5. // Package: Core
  6. // Module: Any
  7. //
  8. // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
  9. // Extracted from Boost 1.33.1 libs and adapted for poco: Peter Schojer/AppliedInformatics 2006-02-02
  10. //
  11. // SPDX-License-Identifier: BSL-1.0
  12. //
  13. #ifndef Foundation_Any_INCLUDED
  14. #define Foundation_Any_INCLUDED
  15. #include "Poco/Exception.h"
  16. #include "Poco/MetaProgramming.h"
  17. #include <algorithm>
  18. #include <typeinfo>
  19. #include <cstring>
  20. namespace Poco {
  21. class Any;
  22. namespace Dynamic {
  23. class Var;
  24. class VarHolder;
  25. template <class> class VarHolderImpl;
  26. }
  27. #ifndef POCO_NO_SOO
  28. #ifndef POCO_ENABLE_CPP11
  29. // C++11 needed for std::aligned_storage
  30. #error "Any SOO can only be enabled with C++11 support"
  31. #endif
  32. template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
  33. union Placeholder
  34. /// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
  35. /// object optimization, when enabled).
  36. ///
  37. /// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
  38. /// it will be placement-new-allocated into the local buffer
  39. /// (i.e. there will be no heap-allocation). The local buffer size is one byte
  40. /// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
  41. /// where the object was allocated (0 => heap, 1 => local).
  42. {
  43. public:
  44. struct Size
  45. {
  46. static const unsigned int value = SizeV;
  47. };
  48. Placeholder ()
  49. {
  50. erase();
  51. }
  52. void erase()
  53. {
  54. std::memset(holder, 0, sizeof(Placeholder));
  55. }
  56. bool isLocal() const
  57. {
  58. return holder[SizeV] != 0;
  59. }
  60. void setLocal(bool local) const
  61. {
  62. holder[SizeV] = local ? 1 : 0;
  63. }
  64. PlaceholderT* content() const
  65. {
  66. if (isLocal())
  67. return reinterpret_cast<PlaceholderT*>(holder);
  68. else
  69. return pHolder;
  70. }
  71. // MSVC71,80 won't extend friendship to nested class (Any::Holder)
  72. #if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
  73. private:
  74. #endif
  75. typedef typename std::aligned_storage<SizeV + 1>::type AlignerType;
  76. PlaceholderT* pHolder;
  77. mutable char holder [SizeV + 1];
  78. AlignerType aligner;
  79. friend class Any;
  80. friend class Dynamic::Var;
  81. friend class Dynamic::VarHolder;
  82. template <class> friend class Dynamic::VarHolderImpl;
  83. };
  84. #else // !POCO_NO_SOO
  85. template <typename PlaceholderT>
  86. union Placeholder
  87. /// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
  88. /// object optimization, when enabled).
  89. ///
  90. /// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
  91. /// it will be placement-new-allocated into the local buffer
  92. /// (i.e. there will be no heap-allocation). The local buffer size is one byte
  93. /// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
  94. /// where the object was allocated (0 => heap, 1 => local).
  95. {
  96. public:
  97. Placeholder ()
  98. {
  99. }
  100. PlaceholderT* content() const
  101. {
  102. return pHolder;
  103. }
  104. // MSVC71,80 won't extend friendship to nested class (Any::Holder)
  105. #if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
  106. private:
  107. #endif
  108. PlaceholderT* pHolder;
  109. friend class Any;
  110. friend class Dynamic::Var;
  111. friend class Dynamic::VarHolder;
  112. template <class> friend class Dynamic::VarHolderImpl;
  113. };
  114. #endif // POCO_NO_SOO
  115. class Any
  116. /// An Any class represents a general type and is capable of storing any type, supporting type-safe extraction
  117. /// of the internally stored data.
  118. ///
  119. /// Code taken from the Boost 1.33.1 library. Original copyright by Kevlin Henney. Modified for Poco
  120. /// by Applied Informatics.
  121. ///
  122. /// Modified for small object optimization support (optionally supported through conditional compilation)
  123. /// by Alex Fabijanic.
  124. {
  125. public:
  126. #ifndef POCO_NO_SOO
  127. Any()
  128. /// Creates an empty any type.
  129. {
  130. }
  131. template<typename ValueType>
  132. Any(const ValueType & value)
  133. /// Creates an any which stores the init parameter inside.
  134. ///
  135. /// Example:
  136. /// Any a(13);
  137. /// Any a(string("12345"));
  138. {
  139. construct(value);
  140. }
  141. Any(const Any& other)
  142. /// Copy constructor, works with both empty and initialized Any values.
  143. {
  144. if ((this != &other) && !other.empty())
  145. construct(other);
  146. }
  147. ~Any()
  148. /// Destructor. If Any is locally held, calls ValueHolder destructor;
  149. /// otherwise, deletes the placeholder from the heap.
  150. {
  151. if (!empty())
  152. {
  153. if (_valueHolder.isLocal())
  154. destruct();
  155. else
  156. delete content();
  157. }
  158. }
  159. Any& swap(Any& other)
  160. /// Swaps the content of the two Anys.
  161. ///
  162. /// When small object optimizaton is enabled, swap only
  163. /// has no-throw guarantee when both (*this and other)
  164. /// objects are allocated on the heap.
  165. {
  166. if (this == &other) return *this;
  167. if (!_valueHolder.isLocal() && !other._valueHolder.isLocal())
  168. {
  169. std::swap(_valueHolder.pHolder, other._valueHolder.pHolder);
  170. }
  171. else
  172. {
  173. Any tmp(*this);
  174. try
  175. {
  176. if (_valueHolder.isLocal()) destruct();
  177. construct(other);
  178. other = tmp;
  179. }
  180. catch (...)
  181. {
  182. construct(tmp);
  183. throw;
  184. }
  185. }
  186. return *this;
  187. }
  188. template<typename ValueType>
  189. Any& operator = (const ValueType& rhs)
  190. /// Assignment operator for all types != Any.
  191. ///
  192. /// Example:
  193. /// Any a = 13;
  194. /// Any a = string("12345");
  195. {
  196. construct(rhs);
  197. return *this;
  198. }
  199. Any& operator = (const Any& rhs)
  200. /// Assignment operator for Any.
  201. {
  202. if ((this != &rhs) && !rhs.empty())
  203. construct(rhs);
  204. else if ((this != &rhs) && rhs.empty())
  205. _valueHolder.erase();
  206. return *this;
  207. }
  208. bool empty() const
  209. /// Returns true if the Any is empty.
  210. {
  211. char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
  212. return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE);
  213. }
  214. const std::type_info & type() const
  215. /// Returns the type information of the stored content.
  216. /// If the Any is empty typeid(void) is returned.
  217. /// It is recommended to always query an Any for its type info before
  218. /// trying to extract data via an AnyCast/RefAnyCast.
  219. {
  220. return empty() ? typeid(void) : content()->type();
  221. }
  222. private:
  223. class ValueHolder
  224. {
  225. public:
  226. virtual ~ValueHolder()
  227. {
  228. }
  229. virtual const std::type_info & type() const = 0;
  230. virtual void clone(Placeholder<ValueHolder>*) const = 0;
  231. };
  232. template<typename ValueType>
  233. class Holder : public ValueHolder
  234. {
  235. public:
  236. Holder(const ValueType & value) : _held(value)
  237. {
  238. }
  239. virtual const std::type_info & type() const
  240. {
  241. return typeid(ValueType);
  242. }
  243. virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
  244. {
  245. if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
  246. {
  247. new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
  248. pPlaceholder->setLocal(true);
  249. }
  250. else
  251. {
  252. pPlaceholder->pHolder = new Holder(_held);
  253. pPlaceholder->setLocal(false);
  254. }
  255. }
  256. ValueType _held;
  257. private:
  258. Holder & operator = (const Holder &);
  259. };
  260. ValueHolder* content() const
  261. {
  262. return _valueHolder.content();
  263. }
  264. template<typename ValueType>
  265. void construct(const ValueType& value)
  266. {
  267. if (sizeof(Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
  268. {
  269. new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
  270. _valueHolder.setLocal(true);
  271. }
  272. else
  273. {
  274. _valueHolder.pHolder = new Holder<ValueType>(value);
  275. _valueHolder.setLocal(false);
  276. }
  277. }
  278. void construct(const Any& other)
  279. {
  280. if (!other.empty())
  281. other.content()->clone(&_valueHolder);
  282. else
  283. _valueHolder.erase();
  284. }
  285. void destruct()
  286. {
  287. content()->~ValueHolder();
  288. }
  289. Placeholder<ValueHolder> _valueHolder;
  290. #else // if POCO_NO_SOO
  291. Any(): _pHolder(0)
  292. /// Creates an empty any type.
  293. {
  294. }
  295. template <typename ValueType>
  296. Any(const ValueType& value):
  297. _pHolder(new Holder<ValueType>(value))
  298. /// Creates an any which stores the init parameter inside.
  299. ///
  300. /// Example:
  301. /// Any a(13);
  302. /// Any a(string("12345"));
  303. {
  304. }
  305. Any(const Any& other):
  306. _pHolder(other._pHolder ? other._pHolder->clone() : 0)
  307. /// Copy constructor, works with both empty and initialized Any values.
  308. {
  309. }
  310. ~Any()
  311. {
  312. delete _pHolder;
  313. }
  314. Any& swap(Any& rhs)
  315. /// Swaps the content of the two Anys.
  316. {
  317. std::swap(_pHolder, rhs._pHolder);
  318. return *this;
  319. }
  320. template <typename ValueType>
  321. Any& operator = (const ValueType& rhs)
  322. /// Assignment operator for all types != Any.
  323. ///
  324. /// Example:
  325. /// Any a = 13;
  326. /// Any a = string("12345");
  327. {
  328. Any(rhs).swap(*this);
  329. return *this;
  330. }
  331. Any& operator = (const Any& rhs)
  332. /// Assignment operator for Any.
  333. {
  334. Any(rhs).swap(*this);
  335. return *this;
  336. }
  337. bool empty() const
  338. /// Returns true if the Any is empty.
  339. {
  340. return !_pHolder;
  341. }
  342. const std::type_info& type() const
  343. /// Returns the type information of the stored content.
  344. /// If the Any is empty typeid(void) is returned.
  345. /// It is recommended to always query an Any for its type info before
  346. /// trying to extract data via an AnyCast/RefAnyCast.
  347. {
  348. return _pHolder ? _pHolder->type() : typeid(void);
  349. }
  350. private:
  351. class ValueHolder
  352. {
  353. public:
  354. virtual ~ValueHolder()
  355. {
  356. }
  357. virtual const std::type_info& type() const = 0;
  358. virtual ValueHolder* clone() const = 0;
  359. };
  360. template <typename ValueType>
  361. class Holder: public ValueHolder
  362. {
  363. public:
  364. Holder(const ValueType& value):
  365. _held(value)
  366. {
  367. }
  368. virtual const std::type_info& type() const
  369. {
  370. return typeid(ValueType);
  371. }
  372. virtual ValueHolder* clone() const
  373. {
  374. return new Holder(_held);
  375. }
  376. ValueType _held;
  377. private:
  378. Holder & operator=(const Holder &);
  379. };
  380. ValueHolder* content() const
  381. {
  382. return _pHolder;
  383. }
  384. private:
  385. ValueHolder* _pHolder;
  386. #endif // POCO_NO_SOO
  387. template <typename ValueType>
  388. friend ValueType* AnyCast(Any*);
  389. template <typename ValueType>
  390. friend ValueType* UnsafeAnyCast(Any*);
  391. };
  392. template <typename ValueType>
  393. ValueType* AnyCast(Any* operand)
  394. /// AnyCast operator used to extract the ValueType from an Any*. Will return a pointer
  395. /// to the stored value.
  396. ///
  397. /// Example Usage:
  398. /// MyType* pTmp = AnyCast<MyType*>(pAny).
  399. /// Will return NULL if the cast fails, i.e. types don't match.
  400. {
  401. return operand && operand->type() == typeid(ValueType)
  402. ? &static_cast<Any::Holder<ValueType>*>(operand->content())->_held
  403. : 0;
  404. }
  405. template <typename ValueType>
  406. const ValueType* AnyCast(const Any* operand)
  407. /// AnyCast operator used to extract a const ValueType pointer from an const Any*. Will return a const pointer
  408. /// to the stored value.
  409. ///
  410. /// Example Usage:
  411. /// const MyType* pTmp = AnyCast<MyType*>(pAny).
  412. /// Will return NULL if the cast fails, i.e. types don't match.
  413. {
  414. return AnyCast<ValueType>(const_cast<Any*>(operand));
  415. }
  416. template <typename ValueType>
  417. ValueType AnyCast(Any& operand)
  418. /// AnyCast operator used to extract a copy of the ValueType from an Any&.
  419. ///
  420. /// Example Usage:
  421. /// MyType tmp = AnyCast<MyType>(anAny).
  422. /// Will throw a BadCastException if the cast fails.
  423. /// Dont use an AnyCast in combination with references, i.e. MyType& tmp = ... or const MyType& tmp = ...
  424. /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
  425. /// these cases.
  426. {
  427. typedef typename TypeWrapper<ValueType>::TYPE NonRef;
  428. NonRef* result = AnyCast<NonRef>(&operand);
  429. if (!result) throw BadCastException("Failed to convert between Any types");
  430. return *result;
  431. }
  432. template <typename ValueType>
  433. ValueType AnyCast(const Any& operand)
  434. /// AnyCast operator used to extract a copy of the ValueType from an const Any&.
  435. ///
  436. /// Example Usage:
  437. /// MyType tmp = AnyCast<MyType>(anAny).
  438. /// Will throw a BadCastException if the cast fails.
  439. /// Dont use an AnyCast in combination with references, i.e. MyType& tmp = ... or const MyType& = ...
  440. /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
  441. /// these cases.
  442. {
  443. typedef typename TypeWrapper<ValueType>::TYPE NonRef;
  444. return AnyCast<NonRef&>(const_cast<Any&>(operand));
  445. }
  446. template <typename ValueType>
  447. const ValueType& RefAnyCast(const Any & operand)
  448. /// AnyCast operator used to return a const reference to the internal data.
  449. ///
  450. /// Example Usage:
  451. /// const MyType& tmp = RefAnyCast<MyType>(anAny);
  452. {
  453. ValueType* result = AnyCast<ValueType>(const_cast<Any*>(&operand));
  454. if (!result) throw BadCastException("RefAnyCast: Failed to convert between const Any types");
  455. return *result;
  456. }
  457. template <typename ValueType>
  458. ValueType& RefAnyCast(Any& operand)
  459. /// AnyCast operator used to return a reference to the internal data.
  460. ///
  461. /// Example Usage:
  462. /// MyType& tmp = RefAnyCast<MyType>(anAny);
  463. {
  464. ValueType* result = AnyCast<ValueType>(&operand);
  465. if (!result) throw BadCastException("RefAnyCast: Failed to convert between Any types");
  466. return *result;
  467. }
  468. template <typename ValueType>
  469. ValueType* UnsafeAnyCast(Any* operand)
  470. /// The "unsafe" versions of AnyCast are not part of the
  471. /// public interface and may be removed at any time. They are
  472. /// required where we know what type is stored in the any and can't
  473. /// use typeid() comparison, e.g., when our types may travel across
  474. /// different shared libraries.
  475. {
  476. return &static_cast<Any::Holder<ValueType>*>(operand->content())->_held;
  477. }
  478. template <typename ValueType>
  479. const ValueType* UnsafeAnyCast(const Any* operand)
  480. /// The "unsafe" versions of AnyCast are not part of the
  481. /// public interface and may be removed at any time. They are
  482. /// required where we know what type is stored in the any and can't
  483. /// use typeid() comparison, e.g., when our types may travel across
  484. /// different shared libraries.
  485. {
  486. return AnyCast<ValueType>(const_cast<Any*>(operand));
  487. }
  488. } // namespace Poco
  489. #endif