You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

567 lines
16 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/util/guid.hpp (originally MOGuidGn.h/.cpp, ::SynesisCom)
  3. *
  4. * Purpose: guid class.
  5. *
  6. * Created: 10th May 2000
  7. * Updated: 12th May 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2000-2010, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file comstl/util/guid.hpp
  40. *
  41. * \brief [C++ only; requires COM] Definition of the comstl::guid class
  42. * (\ref group__library__utility__com "COM Utility" Library).
  43. */
  44. #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_GUID
  45. #define COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_GUID
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_GUID_MAJOR 4
  48. # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_GUID_MINOR 3
  49. # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_GUID_REVISION 2
  50. # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_GUID_EDIT 46
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Includes
  54. */
  55. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  56. # include <comstl/comstl.h>
  57. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  58. #ifndef COMSTL_INCL_COMSTL_SHIMS_ACCESS_HPP_STRING
  59. # include <comstl/shims/access/string.hpp>
  60. #endif /* !COMSTL_INCL_COMSTL_SHIMS_ACCESS_HPP_STRING */
  61. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  62. # ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
  63. # include <comstl/error/exceptions.hpp>
  64. # endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
  65. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  66. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
  67. # include <stlsoft/util/std_swap.hpp>
  68. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP */
  69. /* /////////////////////////////////////////////////////////////////////////
  70. * Namespace
  71. */
  72. #ifndef _COMSTL_NO_NAMESPACE
  73. # if defined(_STLSOFT_NO_NAMESPACE) || \
  74. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  75. /* There is no stlsoft namespace, so must define ::comstl */
  76. namespace comstl
  77. {
  78. # else
  79. /* Define stlsoft::comstl_project */
  80. namespace stlsoft
  81. {
  82. namespace comstl_project
  83. {
  84. # endif /* _STLSOFT_NO_NAMESPACE */
  85. #endif /* !_COMSTL_NO_NAMESPACE */
  86. /* /////////////////////////////////////////////////////////////////////////
  87. * Classes
  88. */
  89. /** \brief Facade for the COM GUID type
  90. *
  91. * \ingroup group__library__utility__com
  92. */
  93. class guid
  94. {
  95. /// \name Types
  96. /// @{
  97. public:
  98. typedef guid class_type;
  99. typedef GUID const& resource_type;
  100. /// @}
  101. /// \name Construction
  102. /// @{
  103. public:
  104. /// \brief Constructs with a new, unique, GUID value
  105. ///
  106. /// \note If a new value cannot be aquired, then an instance of
  107. /// com_exception is thrown if compiled under conditions where exceptions
  108. /// are supported (STLSOFT_CF_EXCEPTION_SUPPORT is defined), or the
  109. /// instance GUID is set to GUID_NULL otherwise.
  110. guid();
  111. /// \brief Constructs with a GUID value equivalent to the given ANSI string
  112. ///
  113. /// \param s The string form of the desired GUID
  114. ///
  115. /// Example: \code
  116. /// guid g("{00000303-0000-0000-C000-000000000046}");
  117. /// \endcode
  118. ///
  119. /// \note If a new value cannot be determined, then an instance of
  120. /// com_exception is thrown if compiled under conditions where exceptions
  121. /// are supported (STLSOFT_CF_EXCEPTION_SUPPORT is defined), or the
  122. /// instance GUID is set to GUID_NULL otherwise.
  123. ss_explicit_k guid(cs_char_a_t const* s);
  124. /// \brief Constructs with a GUID value equivalent to the given Unicode string
  125. ///
  126. /// \param s The string form of the desired GUID
  127. ///
  128. /// Example: \code
  129. /// guid g(L"{00000303-0000-0000-C000-000000000046}");
  130. /// \endcode
  131. ///
  132. /// \note If a new value cannot be determined, then an instance of
  133. /// com_exception is thrown if compiled under conditions where exceptions
  134. /// are supported (STLSOFT_CF_EXCEPTION_SUPPORT is defined), or the
  135. /// instance GUID is set to GUID_NULL otherwise.
  136. ss_explicit_k guid(cs_char_w_t const* s);
  137. /// \brief Copy constructs from the given GUID
  138. ss_explicit_k guid(GUID const& g);
  139. /// \brief Copy constructor
  140. guid(class_type const& rhs);
  141. /// \brief Copies the given instance
  142. guid& operator =(class_type const& rhs);
  143. /// \brief Assigns to a GUID value equivalent to the given string
  144. ///
  145. /// \param s The string form of the desired GUID
  146. ///
  147. /// Example: \code
  148. /// guid g;
  149. ///
  150. /// g = "{00000303-0000-0000-C000-000000000046}";
  151. /// \endcode
  152. ///
  153. /// \note If a new value cannot be determined, then an instance of
  154. /// com_exception is thrown if compiled under conditions where exceptions
  155. /// are supported (STLSOFT_CF_EXCEPTION_SUPPORT is defined), or the
  156. /// instance GUID is set to GUID_NULL otherwise.
  157. guid& operator =(cs_char_a_t const* s);
  158. /// \brief Assigns to a GUID value equivalent to the given string
  159. ///
  160. /// \param s The string form of the desired GUID
  161. ///
  162. /// Example: \code
  163. /// guid g;
  164. ///
  165. /// g = L"{00000303-0000-0000-C000-000000000046}";
  166. /// \endcode
  167. ///
  168. /// \note If a new value cannot be determined, then an instance of
  169. /// com_exception is thrown if compiled under conditions where exceptions
  170. /// are supported (STLSOFT_CF_EXCEPTION_SUPPORT is defined), or the
  171. /// instance GUID is set to GUID_NULL otherwise.
  172. guid& operator =(cs_char_w_t const* s);
  173. /// \brief Copies the given GUID value
  174. guid& operator =(GUID const& g);
  175. /// @}
  176. /// \name Accessors
  177. /// @{
  178. public:
  179. GUID const& get() const;
  180. /// @}
  181. /// \name Comparison
  182. /// @{
  183. public:
  184. /// \brief Evaluates whether the value is equivalent to the given argument
  185. cs_bool_t equal(class_type const& rhs) const;
  186. /// \brief Evaluates whether the value is equivalent to the given argument
  187. cs_bool_t equal(GUID const& rhs) const;
  188. /// @}
  189. /// \name Operations
  190. /// @{
  191. public:
  192. /// \brief Swaps the contents with the given instance
  193. void swap(class_type& rhs) stlsoft_throw_0();
  194. /// @}
  195. /// \name Members
  196. /// @{
  197. private:
  198. GUID m_guid;
  199. /// @}
  200. };
  201. /* /////////////////////////////////////////////////////////////////////////
  202. * String access shims
  203. */
  204. /** \brief \ref group__concept__shim__string_access__c_str_data for comstl::guid
  205. *
  206. * \ingroup group__concept__shim__string_access
  207. */
  208. inline c_str_ptr_GUID_proxy<TCHAR> c_str_data(comstl_ns_qual(guid) const& g)
  209. {
  210. return stlsoft_ns_qual(c_str_data)(g.get());
  211. }
  212. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  213. inline c_str_ptr_GUID_proxy<cs_char_a_t> c_str_data_a(comstl_ns_qual(guid) const& g)
  214. {
  215. return stlsoft_ns_qual(c_str_data_a)(g.get());
  216. }
  217. inline c_str_ptr_GUID_proxy<cs_char_w_t> c_str_data_w(comstl_ns_qual(guid) const& g)
  218. {
  219. return stlsoft_ns_qual(c_str_data_w)(g.get());
  220. }
  221. inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_data_o(comstl_ns_qual(guid) const& g)
  222. {
  223. return stlsoft_ns_qual(c_str_data_o)(g.get());
  224. }
  225. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  226. /** \brief \ref group__concept__shim__string_access__c_str_len for comstl::guid
  227. *
  228. * \ingroup group__concept__shim__string_access
  229. */
  230. inline cs_size_t c_str_len(comstl_ns_qual(guid) const& g)
  231. {
  232. return stlsoft_ns_qual(c_str_len)(g.get());
  233. }
  234. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  235. inline cs_size_t c_str_len_a(comstl_ns_qual(guid) const& g)
  236. {
  237. return stlsoft_ns_qual(c_str_len_a)(g.get());
  238. }
  239. inline cs_size_t c_str_len_w(comstl_ns_qual(guid) const& g)
  240. {
  241. return stlsoft_ns_qual(c_str_len_w)(g.get());
  242. }
  243. inline cs_size_t c_str_len_o(comstl_ns_qual(guid) const& g)
  244. {
  245. return stlsoft_ns_qual(c_str_len_o)(g.get());
  246. }
  247. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  248. /** \brief \ref group__concept__shim__string_access__c_str_ptr for comstl::guid
  249. *
  250. * \ingroup group__concept__shim__string_access
  251. */
  252. inline c_str_ptr_GUID_proxy<TCHAR> c_str_ptr(comstl_ns_qual(guid) const& g)
  253. {
  254. return stlsoft_ns_qual(c_str_ptr)(g.get());
  255. }
  256. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  257. inline c_str_ptr_GUID_proxy<cs_char_a_t> c_str_ptr_a(comstl_ns_qual(guid) const& g)
  258. {
  259. return stlsoft_ns_qual(c_str_ptr_a)(g.get());
  260. }
  261. inline c_str_ptr_GUID_proxy<cs_char_w_t> c_str_ptr_w(comstl_ns_qual(guid) const& g)
  262. {
  263. return stlsoft_ns_qual(c_str_ptr_w)(g.get());
  264. }
  265. inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr_o(comstl_ns_qual(guid) const& g)
  266. {
  267. return stlsoft_ns_qual(c_str_ptr_o)(g.get());
  268. }
  269. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  270. /** \brief \ref group__concept__shim__string_access__c_str_ptr_null for comstl::guid
  271. *
  272. * \ingroup group__concept__shim__string_access
  273. */
  274. inline c_str_ptr_GUID_proxy<TCHAR> c_str_ptr_null(comstl_ns_qual(guid) const& g)
  275. {
  276. return stlsoft_ns_qual(c_str_ptr_null)(g.get());
  277. }
  278. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  279. inline c_str_ptr_GUID_proxy<cs_char_a_t> c_str_ptr_null_a(comstl_ns_qual(guid) const& g)
  280. {
  281. return stlsoft_ns_qual(c_str_ptr_null_a)(g.get());
  282. }
  283. inline c_str_ptr_GUID_proxy<cs_char_w_t> c_str_ptr_null_w(comstl_ns_qual(guid) const& g)
  284. {
  285. return stlsoft_ns_qual(c_str_ptr_null_w)(g.get());
  286. }
  287. inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr_null_o(comstl_ns_qual(guid) const& g)
  288. {
  289. return stlsoft_ns_qual(c_str_ptr_null_o)(g.get());
  290. }
  291. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  292. /* /////////////////////////////////////////////////////////////////////////
  293. * Operators
  294. */
  295. inline cs_bool_t operator ==(guid const& lhs, guid const& rhs)
  296. {
  297. return lhs.equal(rhs);
  298. }
  299. inline cs_bool_t operator !=(guid const& lhs, guid const& rhs)
  300. {
  301. return !operator ==(lhs, rhs);
  302. }
  303. inline cs_bool_t operator ==(guid const& lhs, GUID const& rhs)
  304. {
  305. return lhs.equal(rhs);
  306. }
  307. inline cs_bool_t operator !=(guid const& lhs, GUID const& rhs)
  308. {
  309. return !operator ==(lhs, rhs);
  310. }
  311. inline cs_bool_t operator ==(GUID const& lhs, guid const& rhs)
  312. {
  313. return rhs.equal(lhs);
  314. }
  315. inline cs_bool_t operator !=(GUID const& lhs, guid const& rhs)
  316. {
  317. return !operator ==(lhs, rhs);
  318. }
  319. ////////////////////////////////////////////////////////////////////////////
  320. // Unit-testing
  321. #ifdef STLSOFT_UNITTEST
  322. # include "./unittest/guid_unittest_.h"
  323. #endif /* STLSOFT_UNITTEST */
  324. /* /////////////////////////////////////////////////////////////////////////
  325. * Implementation
  326. */
  327. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  328. inline guid::guid()
  329. {
  330. HRESULT hr = ::CoCreateGuid(&m_guid);
  331. if(FAILED(hr))
  332. {
  333. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  334. STLSOFT_THROW_X(com_exception("Could not allocate GUID", hr));
  335. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  336. m_guid = GUID_NULL;
  337. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  338. }
  339. }
  340. inline /* ss_explicit_k */ guid::guid(cs_char_a_t const* s)
  341. {
  342. OLECHAR osz[1 + COMSTL_CCH_GUID];
  343. HRESULT hr = S_OK;
  344. switch(::MultiByteToWideChar(0, 0, s, -1, &osz[0], 1 + COMSTL_CCH_GUID))
  345. {
  346. case 1 + COMSTL_CCH_GUID:
  347. osz[COMSTL_CCH_GUID] = L'\0';
  348. hr = ::CLSIDFromString(osz, &m_guid);
  349. break;
  350. default:
  351. if(S_OK == (hr = HRESULT_FROM_WIN32(::GetLastError())))
  352. {
  353. hr = E_INVALIDARG;
  354. }
  355. break;
  356. }
  357. if(FAILED(hr))
  358. {
  359. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  360. STLSOFT_THROW_X(com_exception("Could not convert string to valid GUID", hr));
  361. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  362. m_guid = GUID_NULL;
  363. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  364. }
  365. }
  366. inline /* ss_explicit_k */ guid::guid(cs_char_w_t const* s)
  367. {
  368. HRESULT hr = ::CLSIDFromString(const_cast<LPOLESTR>(s), &m_guid);
  369. if(FAILED(hr))
  370. {
  371. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  372. STLSOFT_THROW_X(com_exception("Could not convert string to valid GUID", hr));
  373. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  374. m_guid = GUID_NULL;
  375. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  376. }
  377. }
  378. inline guid::guid(GUID const& g)
  379. : m_guid(g)
  380. {}
  381. inline guid::guid(guid const& rhs)
  382. : m_guid(rhs.m_guid)
  383. {}
  384. inline guid &guid::operator =(guid const& rhs)
  385. {
  386. m_guid = rhs.m_guid;
  387. return *this;
  388. }
  389. inline guid &guid::operator =(cs_char_a_t const* s)
  390. {
  391. guid t(s);
  392. t.swap(*this);
  393. return *this;
  394. }
  395. inline guid &guid::operator =(cs_char_w_t const* s)
  396. {
  397. guid t(s);
  398. t.swap(*this);
  399. return *this;
  400. }
  401. inline guid &guid::operator =(GUID const& g)
  402. {
  403. guid t(g);
  404. t.swap(*this);
  405. return *this;
  406. }
  407. inline GUID const& guid::get() const
  408. {
  409. return m_guid;
  410. }
  411. inline cs_bool_t guid::equal(class_type const& rhs) const
  412. {
  413. return 0 != IsEqualGUID(m_guid, rhs.m_guid);
  414. }
  415. inline cs_bool_t guid::equal(GUID const& rhs) const
  416. {
  417. return 0 != IsEqualGUID(m_guid, rhs);
  418. }
  419. inline void guid::swap(guid::class_type& rhs) stlsoft_throw_0()
  420. {
  421. stlsoft_ns_qual(std_swap)(m_guid, rhs.m_guid);
  422. }
  423. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  424. /* ////////////////////////////////////////////////////////////////////// */
  425. #ifndef _COMSTL_NO_NAMESPACE
  426. # if defined(_STLSOFT_NO_NAMESPACE) || \
  427. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  428. } // namespace comstl
  429. # else
  430. } // namespace stlsoft::comstl_project
  431. } // namespace stlsoft
  432. # endif /* _STLSOFT_NO_NAMESPACE */
  433. #endif /* !_COMSTL_NO_NAMESPACE */
  434. /* /////////////////////////////////////////////////////////////////////////
  435. * Namespace
  436. *
  437. * The string access shims exist either in the stlsoft namespace, or in the
  438. * global namespace. This is required by the lookup rules.
  439. *
  440. */
  441. #ifndef _COMSTL_NO_NAMESPACE
  442. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  443. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  444. namespace stlsoft
  445. {
  446. # else /* ? _STLSOFT_NO_NAMESPACE */
  447. /* There is no stlsoft namespace, so must define in the global namespace */
  448. # endif /* !_STLSOFT_NO_NAMESPACE */
  449. using ::comstl::c_str_data;
  450. using ::comstl::c_str_data_a;
  451. using ::comstl::c_str_data_w;
  452. using ::comstl::c_str_data_o;
  453. using ::comstl::c_str_len;
  454. using ::comstl::c_str_len_a;
  455. using ::comstl::c_str_len_w;
  456. using ::comstl::c_str_len_o;
  457. using ::comstl::c_str_ptr;
  458. using ::comstl::c_str_ptr_a;
  459. using ::comstl::c_str_ptr_w;
  460. using ::comstl::c_str_ptr_o;
  461. using ::comstl::c_str_ptr_null;
  462. using ::comstl::c_str_ptr_null_a;
  463. using ::comstl::c_str_ptr_null_w;
  464. using ::comstl::c_str_ptr_null_o;
  465. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  466. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  467. } // namespace stlsoft
  468. # else /* ? _STLSOFT_NO_NAMESPACE */
  469. /* There is no stlsoft namespace, so must define in the global namespace */
  470. # endif /* !_STLSOFT_NO_NAMESPACE */
  471. #endif /* !_COMSTL_NO_NAMESPACE */
  472. /* ////////////////////////////////////////////////////////////////////// */
  473. #endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_GUID */
  474. /* ///////////////////////////// end of file //////////////////////////// */