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.

782 lines
22 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/shims/access/string/variant.hpp
  3. *
  4. * Purpose: Contains classes and functions for dealing with OLE/COM strings.
  5. *
  6. * Created: 24th May 2002
  7. * Updated: 27th April 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2002-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/shims/access/string/variant.hpp
  40. *
  41. * \brief [C++] Definition of the string access shims for
  42. * <code>VARIANT</code>
  43. * (\ref group__concept__shim__string_access "String Access Shims" Concept).
  44. */
  45. #ifndef COMSTL_INCL_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT
  46. #define COMSTL_INCL_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define COMSTL_VER_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT_MAJOR 5
  49. # define COMSTL_VER_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT_MINOR 0
  50. # define COMSTL_VER_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT_REVISION 6
  51. # define COMSTL_VER_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT_EDIT 115
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  57. # include <comstl/comstl.h>
  58. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  59. #ifndef COMSTL_INCL_COMSTL_STRING_H_BSTR_FUNCTIONS
  60. # include <comstl/string/BSTR_functions.h>
  61. #endif /* !COMSTL_INCL_COMSTL_STRING_H_BSTR_FUNCTIONS */
  62. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  63. # include <stlsoft/shims/access/string.hpp>
  64. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  65. #ifndef STLSOFT_INCL_H_WCHAR
  66. # define STLSOFT_INCL_H_WCHAR
  67. # include <wchar.h>
  68. #endif /* !STLSOFT_INCL_H_WCHAR */
  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 This class provides an intermediary object that may be returned by the
  90. * c_str_ptr_null() function, such that the text of a given variant
  91. * may be accessed as a null-terminated string.
  92. *
  93. * \ingroup group__concept__shim__string_access
  94. *
  95. */
  96. class c_str_null_VARIANT_proxy
  97. {
  98. public:
  99. typedef c_str_null_VARIANT_proxy class_type;
  100. // Construction
  101. public:
  102. /// Constructs an instance of the proxy from the given BSTR
  103. ///
  104. /// \param s The BSTR from which the text will be retrieved
  105. ss_explicit_k c_str_null_VARIANT_proxy(const BSTR s)
  106. : m_bstr(s)
  107. , m_own(false)
  108. {}
  109. /// Constructs an instance of the proxy from the given BSTR
  110. ///
  111. /// \param ps Pointer to the BSTR from which the text will be retrieved
  112. ss_explicit_k c_str_null_VARIANT_proxy(BSTR *ps)
  113. : m_bstr(*ps)
  114. , m_own(true)
  115. {
  116. if(m_own)
  117. {
  118. *ps = NULL;
  119. }
  120. }
  121. /// Default constructor
  122. c_str_null_VARIANT_proxy()
  123. : m_bstr(NULL)
  124. , m_own(false)
  125. {}
  126. #ifdef STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
  127. /// Move constructor
  128. ///
  129. /// This <a href = "http://synesis.com.au/resources/articles/cpp/movectors.pdf">move constructor</a>
  130. /// is for circumstances when the compiler does not, or cannot, apply the
  131. /// return value optimisation. It causes the contents of \c rhs to be
  132. /// transferred into the constructing instance. This is completely safe
  133. /// because the \c rhs instance will never be accessed in its own right, so
  134. /// does not need to maintain ownership of its contents.
  135. c_str_null_VARIANT_proxy(class_type& rhs)
  136. : m_bstr(rhs.m_bstr)
  137. , m_own(rhs.m_own)
  138. {
  139. move_lhs_from_rhs(rhs).m_bstr = NULL;
  140. move_lhs_from_rhs(rhs).m_own = false;
  141. }
  142. #else /* ? STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  143. // Copy constructor
  144. c_str_null_VARIANT_proxy(class_type const& rhs)
  145. : m_bstr(bstr_dup(rhs.m_bstr))
  146. {}
  147. #endif /* STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  148. /// Releases any storage aquired by the proxy
  149. ~c_str_null_VARIANT_proxy() stlsoft_throw_0()
  150. {
  151. if(m_own)
  152. {
  153. ::SysFreeString(m_bstr);
  154. }
  155. }
  156. // Accessors
  157. public:
  158. /// Returns a null-terminated string representing the VARIANT contents, or
  159. /// NULL if the VARIANT contents cannot be converted to text.
  160. operator LPCOLESTR () const
  161. {
  162. return m_bstr;
  163. }
  164. // Members
  165. private:
  166. BSTR m_bstr;
  167. cs_bool_t m_own;
  168. // Not to be implemented
  169. private:
  170. void operator =(class_type const& rhs);
  171. };
  172. /** \brief This class provides an intermediary object that may be returned by the
  173. * c_str_ptr_w() function, such that the text of a given variant
  174. * may be accessed as a null-terminated string.
  175. *
  176. * \ingroup group__concept__shim__string_access
  177. *
  178. */
  179. class c_str_VARIANT_proxy_w
  180. {
  181. public:
  182. typedef c_str_VARIANT_proxy_w class_type;
  183. // Construction
  184. public:
  185. /// Constructs an instance of the proxy from the given BSTR
  186. ///
  187. /// \param s The BSTR from which the text will be retrieved
  188. ss_explicit_k c_str_VARIANT_proxy_w(BSTR &s)
  189. : m_bstr(s)
  190. {
  191. s = NULL;
  192. }
  193. #ifdef STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
  194. /// Move constructor
  195. ///
  196. /// This <a href = "http://synesis.com.au/resources/articles/cpp/movectors.pdf">move constructor</a>
  197. /// is for circumstances when the compiler does not, or cannot, apply the
  198. /// return value optimisation. It causes the contents of \c rhs to be
  199. /// transferred into the constructing instance. This is completely safe
  200. /// because the \c rhs instance will never be accessed in its own right, so
  201. /// does not need to maintain ownership of its contents.
  202. c_str_VARIANT_proxy_w(class_type& rhs)
  203. : m_bstr(rhs.m_bstr)
  204. {
  205. move_lhs_from_rhs(rhs).m_bstr = NULL;
  206. }
  207. #else /* ? STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  208. // Copy constructor
  209. c_str_VARIANT_proxy_w(class_type const& rhs)
  210. : m_bstr(bstr_dup(rhs.m_bstr))
  211. {}
  212. #endif /* STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  213. /// Releases any storage aquired by the proxy
  214. ~c_str_VARIANT_proxy_w() stlsoft_throw_0()
  215. {
  216. ::SysFreeString(m_bstr);
  217. }
  218. // Accessors
  219. public:
  220. /// Returns a null-terminated string representing the VARIANT contents.
  221. operator LPCOLESTR () const
  222. {
  223. return (m_bstr == NULL) ? L"" : m_bstr;
  224. }
  225. // Members
  226. private:
  227. BSTR m_bstr;
  228. // Not to be implemented
  229. private:
  230. void operator =(class_type const& rhs);
  231. };
  232. /** \brief This class provides an intermediary object that may be returned by the
  233. * c_str_ptr_a() function, such that the text of a given variant
  234. * may be accessed as a null-terminated string.
  235. *
  236. * \ingroup group__concept__shim__string_access
  237. *
  238. */
  239. class c_str_VARIANT_proxy_a
  240. {
  241. public:
  242. typedef c_str_VARIANT_proxy_a class_type;
  243. typedef c_str_VARIANT_proxy_w class_w_type;
  244. // Construction
  245. public:
  246. /// Constructs an instance of the proxy from the given c_str_VARIANT_proxy_w
  247. ///
  248. /// \param rhs The c_str_VARIANT_proxy_w from which the text will be retrieved
  249. ss_explicit_k c_str_VARIANT_proxy_a(class_w_type rhs)
  250. : m_proxyw(rhs)
  251. , m_buffer(0)
  252. {}
  253. #ifdef STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
  254. /// Move constructor
  255. ///
  256. /// This <a href = "http://synesis.com.au/resources/articles/cpp/movectors.pdf">move constructor</a>
  257. /// is for circumstances when the compiler does not, or cannot, apply the
  258. /// return value optimisation. It causes the contents of \c rhs to be
  259. /// transferred into the constructing instance. This is completely safe
  260. /// because the \c rhs instance will never be accessed in its own right, so
  261. /// does not need to maintain ownership of its contents.
  262. c_str_VARIANT_proxy_a(class_type& rhs)
  263. : m_proxyw(rhs.m_proxyw)
  264. , m_buffer(rhs.m_buffer)
  265. {
  266. move_lhs_from_rhs(rhs).m_buffer = NULL;
  267. }
  268. #else /* ? STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  269. // Copy constructor
  270. c_str_VARIANT_proxy_a(class_type const& rhs)
  271. : m_proxyw(rhs.m_proxyw)
  272. , m_buffer(NULL)
  273. {}
  274. #endif /* STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
  275. /// Releases any storage aquired by the proxy
  276. ~c_str_VARIANT_proxy_a() stlsoft_throw_0()
  277. {
  278. if(m_buffer != empty_string_())
  279. {
  280. ::CoTaskMemFree(m_buffer);
  281. }
  282. }
  283. // Accessors
  284. public:
  285. /// Returns a null-terminated string representing the VARIANT contents.
  286. operator cs_char_a_t const* () const
  287. {
  288. if(NULL == m_buffer)
  289. {
  290. LPCOLESTR w_value = m_proxyw;
  291. cs_char_a_t *&buffer_ = const_cast<class_type*>(this)->m_buffer;
  292. if( NULL == w_value ||
  293. L'\0' == *w_value)
  294. {
  295. buffer_ = empty_string_();
  296. }
  297. else
  298. {
  299. cs_size_t cch = ::SysStringLen((BSTR)w_value);
  300. buffer_ = static_cast<cs_char_a_t *>(::CoTaskMemAlloc((1 + cch) * sizeof(cs_char_a_t)));
  301. if(NULL == buffer_)
  302. {
  303. buffer_ = empty_string_();
  304. }
  305. else
  306. {
  307. int n = ::WideCharToMultiByte(0, 0, w_value, -1, buffer_, static_cast<int>(cch + 1), NULL, NULL);
  308. #ifdef WIN32
  309. if(0 == n)
  310. #else /* ? WIN32 */
  311. # error Not currently implemented for operating systems other than Win32
  312. #endif /* WIN32 */
  313. {
  314. // TODO: report failure to convert via exception
  315. }
  316. }
  317. }
  318. }
  319. return m_buffer;
  320. }
  321. // Implementation
  322. private:
  323. static cs_char_a_t *empty_string_()
  324. {
  325. // This character array is initialised to 0, which conveniently happens to
  326. // be the empty string, by the module/application load, so it is
  327. // guaranteed to be valid, and there are no threading/race conditions
  328. static cs_char_a_t s_empty[1];
  329. COMSTL_ASSERT(s_empty[0] == '\0'); // Paranoid check
  330. return s_empty;
  331. }
  332. // Members
  333. private:
  334. c_str_VARIANT_proxy_w m_proxyw;
  335. cs_char_a_t *m_buffer;
  336. // Not to be implemented
  337. private:
  338. void operator =(class_type const& rhs);
  339. };
  340. /* /////////////////////////////////////////////////////////////////////////
  341. * Equivalence testing
  342. */
  343. // c_str_null_VARIANT_proxy
  344. inline cs_bool_t operator ==(LPCOLESTR lhs, c_str_null_VARIANT_proxy const& rhs)
  345. {
  346. return lhs == static_cast<LPCOLESTR>(rhs);
  347. }
  348. inline cs_bool_t operator ==(c_str_null_VARIANT_proxy const& lhs, LPCOLESTR rhs)
  349. {
  350. return static_cast<LPCOLESTR>(lhs) == rhs;
  351. }
  352. inline cs_bool_t operator !=(LPCOLESTR lhs, c_str_null_VARIANT_proxy const& rhs)
  353. {
  354. return lhs != static_cast<LPCOLESTR>(rhs);
  355. }
  356. inline cs_bool_t operator !=(c_str_null_VARIANT_proxy const& lhs, LPCOLESTR rhs)
  357. {
  358. return static_cast<LPCOLESTR>(lhs) != rhs;
  359. }
  360. // c_str_VARIANT_proxy_a
  361. inline cs_bool_t operator ==(LPCSTR lhs, c_str_VARIANT_proxy_a const& rhs)
  362. {
  363. return lhs == static_cast<LPCSTR>(rhs);
  364. }
  365. inline cs_bool_t operator ==(c_str_VARIANT_proxy_a const& lhs, LPCSTR rhs)
  366. {
  367. return static_cast<LPCSTR>(lhs) == rhs;
  368. }
  369. inline cs_bool_t operator !=(LPCSTR lhs, c_str_VARIANT_proxy_a const& rhs)
  370. {
  371. return lhs != static_cast<LPCSTR>(rhs);
  372. }
  373. inline cs_bool_t operator !=(c_str_VARIANT_proxy_a const& lhs, LPCSTR rhs)
  374. {
  375. return static_cast<LPCSTR>(lhs) != rhs;
  376. }
  377. // c_str_VARIANT_proxy_w
  378. inline cs_bool_t operator ==(LPCOLESTR lhs, c_str_VARIANT_proxy_w const& rhs)
  379. {
  380. return lhs == static_cast<LPCOLESTR>(rhs);
  381. }
  382. inline cs_bool_t operator ==(c_str_VARIANT_proxy_w const& lhs, LPCOLESTR rhs)
  383. {
  384. return static_cast<LPCOLESTR>(lhs) == rhs;
  385. }
  386. inline cs_bool_t operator !=(LPCOLESTR lhs, c_str_VARIANT_proxy_w const& rhs)
  387. {
  388. return lhs != static_cast<LPCOLESTR>(rhs);
  389. }
  390. inline cs_bool_t operator !=(c_str_VARIANT_proxy_w const& lhs, LPCOLESTR rhs)
  391. {
  392. return static_cast<LPCOLESTR>(lhs) != rhs;
  393. }
  394. /* /////////////////////////////////////////////////////////////////////////
  395. * IOStream compatibility
  396. */
  397. template <ss_typename_param_k S>
  398. inline S& operator <<(S& s, c_str_null_VARIANT_proxy const& shim)
  399. {
  400. s << static_cast<LPCOLESTR>(shim);
  401. return s;
  402. }
  403. template <ss_typename_param_k S>
  404. inline S& operator <<(S& s, c_str_VARIANT_proxy_w const& shim)
  405. {
  406. s << static_cast<LPCOLESTR>(shim);
  407. return s;
  408. }
  409. template <ss_typename_param_k S>
  410. inline S& operator <<(S& s, c_str_VARIANT_proxy_a const& shim)
  411. {
  412. s << static_cast<cs_char_a_t const*>(shim);
  413. return s;
  414. }
  415. /* /////////////////////////////////////////////////////////////////////////
  416. * c_str_data
  417. *
  418. * This can be applied to an expression, and the return value is either a
  419. * pointer to the character string or to an empty string.
  420. */
  421. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  422. inline c_str_VARIANT_proxy_a c_str_data_a(VARIANT const& v)
  423. {
  424. VARIANT vs;
  425. HRESULT hr;
  426. ::VariantInit(&vs);
  427. hr = ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, VARIANT_ALPHABOOL, VT_BSTR);
  428. if(FAILED(hr))
  429. {
  430. vs.bstrVal = NULL;
  431. }
  432. return c_str_VARIANT_proxy_a(c_str_VARIANT_proxy_w(vs.bstrVal));
  433. }
  434. inline c_str_VARIANT_proxy_w c_str_data_w(VARIANT const& v)
  435. {
  436. VARIANT vs;
  437. HRESULT hr;
  438. ::VariantInit(&vs);
  439. hr = ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, VARIANT_ALPHABOOL, VT_BSTR);
  440. if(FAILED(hr))
  441. {
  442. vs.bstrVal = NULL;
  443. }
  444. return c_str_VARIANT_proxy_w(vs.bstrVal);
  445. }
  446. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  447. /** \brief Returns the corresponding possibly unterminated C-string pointer of the VARIANT \c v
  448. *
  449. * \ingroup group__concept__shim__string_access
  450. *
  451. */
  452. #ifdef UNICODE
  453. inline c_str_VARIANT_proxy_w c_str_data(VARIANT const& v)
  454. #else /* ? UNICODE */
  455. inline c_str_VARIANT_proxy_a c_str_data(VARIANT const& v)
  456. #endif /* UNICODE */
  457. {
  458. #ifdef UNICODE
  459. return c_str_data_w(v);
  460. #else /* ? UNICODE */
  461. return c_str_data_a(v);
  462. #endif /* UNICODE */
  463. }
  464. /* /////////////////////////////////////////////////////////////////////////
  465. * c_str_len
  466. *
  467. * This can be applied to an expression, and the return value is the number of
  468. * characters in the character string in the expression.
  469. */
  470. /** \brief Returns the length (in characters) of the VARIANT \c v, <b><i>not</i></b> including the null-terminating character
  471. *
  472. * \ingroup group__concept__shim__string_access
  473. *
  474. */
  475. inline cs_size_t c_str_len_a(VARIANT const& v)
  476. {
  477. if( v.vt == VT_NULL ||
  478. v.vt == VT_EMPTY)
  479. {
  480. return 0;
  481. }
  482. else
  483. {
  484. return stlsoft_ns_qual(c_str_len_a)(c_str_data_a(v));
  485. }
  486. }
  487. /** \brief Returns the length (in characters) of the VARIANT \c v, <b><i>not</i></b> including the null-terminating character
  488. *
  489. * \ingroup group__concept__shim__string_access
  490. *
  491. */
  492. inline cs_size_t c_str_len_w(VARIANT const& v)
  493. {
  494. if(v.vt == VT_BSTR)
  495. {
  496. return v.bstrVal != NULL ? ::SysStringLen(v.bstrVal) : 0;
  497. }
  498. else if(v.vt == VT_NULL ||
  499. v.vt == VT_EMPTY)
  500. {
  501. return 0;
  502. }
  503. else
  504. {
  505. return stlsoft_ns_qual(c_str_len_w)(c_str_data_w(v));
  506. }
  507. }
  508. /** \brief Returns the length (in characters) of the VARIANT \c v, <b><i>not</i></b> including the null-terminating character
  509. *
  510. * \ingroup group__concept__shim__string_access
  511. *
  512. */
  513. inline cs_size_t c_str_len(VARIANT const& v)
  514. {
  515. #ifdef UNICODE
  516. return c_str_len_w(v);
  517. #else /* ? UNICODE */
  518. return c_str_len_a(v);
  519. #endif /* UNICODE */
  520. }
  521. /* /////////////////////////////////////////////////////////////////////////
  522. * c_str_ptr
  523. *
  524. * This can be applied to an expression, and the return value is either a
  525. * pointer to the character string or to an empty string.
  526. */
  527. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  528. inline c_str_VARIANT_proxy_a c_str_ptr_a(VARIANT const& v)
  529. {
  530. return c_str_data_a(v);
  531. }
  532. inline c_str_VARIANT_proxy_w c_str_ptr_w(VARIANT const& v)
  533. {
  534. return c_str_data_w(v);
  535. }
  536. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  537. /** \brief Returns the corresponding C-string pointer of the VARIANT \c v
  538. *
  539. * \ingroup group__concept__shim__string_access
  540. *
  541. */
  542. #ifdef UNICODE
  543. inline c_str_VARIANT_proxy_w c_str_ptr(VARIANT const& v)
  544. #else /* ? UNICODE */
  545. inline c_str_VARIANT_proxy_a c_str_ptr(VARIANT const& v)
  546. #endif /* UNICODE */
  547. {
  548. #ifdef UNICODE
  549. return c_str_ptr_w(v);
  550. #else /* ? UNICODE */
  551. return c_str_ptr_a(v);
  552. #endif /* UNICODE */
  553. }
  554. /* /////////////////////////////////////////////////////////////////////////
  555. * c_str_ptr_null
  556. *
  557. * This can be applied to an expression, and the return value is either a
  558. * pointer to the character string or NULL.
  559. */
  560. /** \brief Returns the corresponding ANSI C-string pointer of the VARIANT \c v, or a null pointer
  561. *
  562. * \ingroup group__concept__shim__string_access
  563. *
  564. */
  565. //inline c_str_null_VARIANT_proxy<cs_char_a_t> c_str_ptr_null_a(VARIANT const& v);
  566. //inline c_str_null_VARIANT_proxy<cs_char_w_t> c_str_ptr_null_w(VARIANT const& v);
  567. //inline c_str_null_VARIANT_proxy<cs_char_o_t> c_str_ptr_null_o(VARIANT const& v);
  568. inline c_str_null_VARIANT_proxy c_str_ptr_null_w(VARIANT const& v)
  569. {
  570. if(v.vt == VT_BSTR)
  571. {
  572. return c_str_null_VARIANT_proxy(v.bstrVal);
  573. }
  574. else if(v.vt == VT_NULL ||
  575. v.vt == VT_EMPTY)
  576. {
  577. return c_str_null_VARIANT_proxy();
  578. }
  579. else
  580. {
  581. VARIANT vs;
  582. HRESULT hr;
  583. ::VariantInit(&vs);
  584. hr = ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, VARIANT_ALPHABOOL, VT_BSTR);
  585. if(FAILED(hr))
  586. {
  587. vs.bstrVal = NULL;
  588. }
  589. return c_str_null_VARIANT_proxy(&vs.bstrVal);
  590. }
  591. }
  592. ////////////////////////////////////////////////////////////////////////////
  593. // Unit-testing
  594. #ifdef STLSOFT_UNITTEST
  595. # include "./unittest/variant_unittest_.h"
  596. #endif /* STLSOFT_UNITTEST */
  597. /* ////////////////////////////////////////////////////////////////////// */
  598. #ifndef _COMSTL_NO_NAMESPACE
  599. # if defined(_STLSOFT_NO_NAMESPACE) || \
  600. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  601. } // namespace comstl
  602. # else
  603. } // namespace stlsoft::comstl_project
  604. } // namespace stlsoft
  605. # endif /* _STLSOFT_NO_NAMESPACE */
  606. #endif /* !_COMSTL_NO_NAMESPACE */
  607. /* /////////////////////////////////////////////////////////////////////////
  608. * Namespace
  609. *
  610. * The string access shims exist either in the stlsoft namespace, or in the
  611. * global namespace. This is required by the lookup rules.
  612. *
  613. */
  614. #ifndef _COMSTL_NO_NAMESPACE
  615. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  616. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  617. namespace stlsoft
  618. {
  619. # else /* ? _STLSOFT_NO_NAMESPACE */
  620. /* There is no stlsoft namespace, so must define in the global namespace */
  621. # endif /* !_STLSOFT_NO_NAMESPACE */
  622. using ::comstl::c_str_data_a;
  623. using ::comstl::c_str_data_w;
  624. //using ::comstl::c_str_data_o;
  625. using ::comstl::c_str_data;
  626. using ::comstl::c_str_len_a;
  627. using ::comstl::c_str_len_w;
  628. //using ::comstl::c_str_len_o;
  629. using ::comstl::c_str_len;
  630. using ::comstl::c_str_ptr_a;
  631. using ::comstl::c_str_ptr_w;
  632. //using ::comstl::c_str_ptr_o;
  633. using ::comstl::c_str_ptr;
  634. //using ::comstl::c_str_ptr_null_a;
  635. using ::comstl::c_str_ptr_null_w;
  636. //using ::comstl::c_str_ptr_null_o;
  637. //using ::comstl::c_str_ptr_null;
  638. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  639. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  640. } // namespace stlsoft
  641. # else /* ? _STLSOFT_NO_NAMESPACE */
  642. /* There is no stlsoft namespace, so must define in the global namespace */
  643. # endif /* !_STLSOFT_NO_NAMESPACE */
  644. #endif /* !_COMSTL_NO_NAMESPACE */
  645. /* /////////////////////////////////////////////////////////////////////////
  646. * Global namespace shims
  647. */
  648. /* This defines stream inserter shim functions for the converters for use
  649. * with the Visual C++ <7.1 standard library.
  650. */
  651. #if defined(STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC) && \
  652. STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION < STLSOFT_CF_DINKUMWARE_VC_VERSION_7_1
  653. # include <iosfwd>
  654. inline comstl_ns_qual_std(basic_ostream)<char>& operator <<(comstl_ns_qual_std(basic_ostream)<char> &stm, comstl_ns_qual(c_str_VARIANT_proxy_a) const& v)
  655. {
  656. return stm << static_cast<char const*>(v);
  657. }
  658. inline comstl_ns_qual_std(basic_ostream)<wchar_t>& operator <<(comstl_ns_qual_std(basic_ostream)<wchar_t> &stm, comstl_ns_qual(c_str_VARIANT_proxy_w) const& v)
  659. {
  660. return stm << static_cast<wchar_t const*>(v);
  661. }
  662. #endif /* library */
  663. /* ////////////////////////////////////////////////////////////////////// */
  664. #endif /* !COMSTL_INCL_COMSTL_SHIMS_ACCESS_STRING_HPP_VARIANT */
  665. /* ///////////////////////////// end of file //////////////////////////// */