STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - Template Software for the Active Template Library COMSTL - The Standard Template Library meets the Component Object Model .netSTL - Standard Template Library meets the Microsoft.NET Common Language Runtime InetSTL - The Standard Template Library meets WinInet MFCSTL - Template Software for the Microsoft Foundation Classes UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

comstl_string_access.h

Go to the documentation of this file.
00001 /* 
00002  * File:        comstl_string_access.h
00003  *
00004  * Purpose:     Contains classes and functions for dealing with OLE/COM strings.
00005  *
00006  * Created:
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2002-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00044 
00045 #ifndef COMSTL_INCL_H_COMSTL_STRING_ACCESS
00046 #define COMSTL_INCL_H_COMSTL_STRING_ACCESS
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define COMSTL_VER_H_COMSTL_STRING_ACCESS_MAJOR     2
00050 # define COMSTL_VER_H_COMSTL_STRING_ACCESS_MINOR     0
00051 # define COMSTL_VER_H_COMSTL_STRING_ACCESS_REVISION  1
00052 # define COMSTL_VER_H_COMSTL_STRING_ACCESS_EDIT      64
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef COMSTL_INCL_H_COMSTL
00060 # include "comstl.h"    // Include the COMSTL root header
00061 #endif /* !COMSTL_INCL_H_COMSTL */
00062 #ifndef COMSTL_INCL_H_COMSTL_BSTR_FUNCTIONS
00063 # include "comstl_bstr_functions.h"
00064 #endif /* !COMSTL_INCL_H_COMSTL_BSTR_FUNCTIONS */
00065 #ifndef STLSOFT_INCL_H_STLSOFT_STRING_ACCESS
00066 # include "stlsoft_string_access.h"
00067 #endif /* !STLSOFT_INCL_H_STLSOFT_STRING_ACCESS */
00068 #include <wchar.h>
00069 
00070 /* 
00071  * Namespace
00072  *
00073  * The COMSTL components are contained within the comstl namespace. This is
00074  * actually an alias for stlsoft::comstl_project,
00075  *
00076  * The definition matrix is as follows:
00077  *
00078  * _STLSOFT_NO_NAMESPACE    _COMSTL_NO_NAMESPACE    comstl definition
00079  * ---------------------    --------------------    -----------------
00080  *  not defined              not defined             = stlsoft::comstl_project
00081  *  not defined              defined                 not defined
00082  *  defined                  not defined             comstl
00083  *  defined                  defined                 not defined
00084  *
00085  */
00086 
00087 #ifndef _COMSTL_NO_NAMESPACE
00088 # if defined(_STLSOFT_NO_NAMESPACE) || \
00089      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00090 /* There is no stlsoft namespace, so must define ::comstl */
00091 namespace comstl
00092 {
00093 # else
00094 /* Define stlsoft::comstl_project */
00095 
00096 namespace stlsoft
00097 {
00098 
00099 namespace comstl_project
00100 {
00101 
00102 # endif /* _STLSOFT_NO_NAMESPACE */
00103 #endif /* !_COMSTL_NO_NAMESPACE */
00104 
00105 /* 
00106 
00108 
00111 
00115 
00120 
00121 /* 
00122  * Constants
00123  */
00124 
00125 const cs_size_t COMSTL_CCH_GUID =   38;
00126 
00127 /* 
00128  * Functions
00129  */
00130 
00131 inline cs_size_t guid2string_w(GUID const &guid, cs_char_w_t buff[1 + COMSTL_CCH_GUID])
00132 {
00133     return static_cast<cs_size_t>(StringFromGUID2(guid, buff, 1 + COMSTL_CCH_GUID));
00134 }
00135 
00136 inline cs_size_t guid2string_a(GUID const &guid, cs_char_a_t buff[1 + COMSTL_CCH_GUID])
00137 {
00138     const cs_size_t COMSTL_CCH_GUID_AND_NULL    =   COMSTL_CCH_GUID + 1;
00139 
00140     /* Don't ask! */
00141 #ifdef __STLSOFT_COMPILER_IS_BORLAND
00142     int         __buff[COMSTL_CCH_GUID_AND_NULL];
00143     cs_char_w_t *_buff  =   (wchar_t *)__buff;
00144 #else
00145     cs_char_w_t _buff[COMSTL_CCH_GUID_AND_NULL];
00146 #endif /* __STLSOFT_COMPILER_IS_BORLAND */
00147     cs_size_t   cch =   guid2string_w(guid, _buff);
00148 
00149     ::WideCharToMultiByte(0, 0, _buff, COMSTL_CCH_GUID_AND_NULL, buff, COMSTL_CCH_GUID_AND_NULL, 0, 0);
00150 
00151     return cch;
00152 }
00153 
00154 /* 
00155  * Classes
00156  */
00157 
00158 /* GUID */
00159 
00163 template <ss_typename_param_k C>
00164 class c_str_ptr_GUID_proxy
00165 {
00166 public:
00167     typedef C                       char_type;
00168     typedef c_str_ptr_GUID_proxy<C> class_type;
00169 
00170 // Construction
00171 public:
00175     ss_explicit_k c_str_ptr_GUID_proxy(GUID const &guid);
00176 
00178     c_str_ptr_GUID_proxy(class_type const &rhs)
00179         : m_(m_buffer)
00180     {
00181         for(int i = 0; i < comstl_num_elements(m_buffer); ++i)
00182         {
00183             m_buffer[i] = rhs.m_buffer[i];
00184         }
00185     }
00186 
00187 // Accessors
00188 public:
00190     operator char_type const *() const
00191     {
00192         return m_buffer;
00193     }
00194 
00195 // Members
00196 private:
00197     char_type const *const  m_;
00198     char_type               m_buffer[1 + COMSTL_CCH_GUID];
00199 
00200 // Not to be implemented
00201 private:
00202     void operator =(class_type const &rhs);
00203 };
00204 
00205 STLSOFT_TEMPLATE_SPECIALISATION
00206 inline c_str_ptr_GUID_proxy<cs_char_a_t>::c_str_ptr_GUID_proxy(GUID const &guid)
00207     : m_(m_buffer)
00208 {
00209 #ifndef __STLSOFT_COMPILER_IS_BORLAND
00210     stlsoft_static_assert(comstl_num_elements(m_buffer) > COMSTL_CCH_GUID);
00211 #endif /* !__STLSOFT_COMPILER_IS_BORLAND */
00212 
00213     guid2string_a(guid, m_buffer);
00214 }
00215 
00216 STLSOFT_TEMPLATE_SPECIALISATION
00217 inline c_str_ptr_GUID_proxy<cs_char_w_t>::c_str_ptr_GUID_proxy(GUID const &guid)
00218     : m_(m_buffer)
00219 {
00220 #ifndef __STLSOFT_COMPILER_IS_BORLAND
00221     stlsoft_static_assert(comstl_num_elements(m_buffer) > COMSTL_CCH_GUID);
00222 #endif /* !__STLSOFT_COMPILER_IS_BORLAND */
00223 
00224     guid2string_w(guid, m_buffer);
00225 }
00226 
00227 
00228 /* VARIANT */
00229 
00233 class c_str_null_VARIANT_proxy
00234 {
00235 public:
00236     typedef c_str_null_VARIANT_proxy    class_type;
00237 
00238 // Construction
00239 public:
00243     ss_explicit_k c_str_null_VARIANT_proxy(const BSTR s)
00244         : m_bstr(s)
00245         , m_own(false)
00246     {}
00247 
00251     ss_explicit_k c_str_null_VARIANT_proxy(BSTR *ps)
00252         : m_bstr(*ps)
00253         , m_own(true)
00254     {
00255         if(m_own)
00256         {
00257             *ps = NULL;
00258         }
00259     }
00260 
00262     c_str_null_VARIANT_proxy()
00263         : m_bstr(NULL)
00264         , m_own(false)
00265     {}
00266 
00267 #ifdef __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
00276     c_str_null_VARIANT_proxy(class_type &rhs)
00277         : m_bstr(rhs.m_bstr)
00278         , m_own(rhs.m_own)
00279     {
00280         move_lhs_from_rhs(rhs).m_bstr  =   NULL;
00281         move_lhs_from_rhs(rhs).m_own   =   false;
00282     }
00283 #else /* ? __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00284     // Copy constructor
00285     c_str_null_VARIANT_proxy(class_type const &rhs)
00286         : m_bstr(bstr_dup(rhs.m_bstr))
00287     {}
00288 #endif /* __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00289 
00291     ~c_str_null_VARIANT_proxy()
00292     {
00293         if(m_own)
00294         {
00295             ::SysFreeString(m_bstr);
00296         }
00297     }
00298 
00299 // Accessors
00300 public:
00303     operator LPCOLESTR () const
00304     {
00305         return m_bstr;
00306     }
00307 
00308 // Members
00309 private:
00310     BSTR        m_bstr;
00311     cs_bool_t   m_own;
00312 
00313 // Not to be implemented
00314 private:
00315     void operator =(class_type const &rhs);
00316 };
00317 
00321 class c_str_VARIANT_proxy_w
00322 {
00323 public:
00324     typedef c_str_VARIANT_proxy_w   class_type;
00325 
00326 // Construction
00327 public:
00331     ss_explicit_k c_str_VARIANT_proxy_w(BSTR &s)
00332         : m_bstr(s)
00333     {
00334         s = NULL;
00335     }
00336 
00337 #ifdef __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
00346     c_str_VARIANT_proxy_w(class_type &rhs)
00347         : m_bstr(rhs.m_bstr)
00348     {
00349         move_lhs_from_rhs(rhs).m_bstr = NULL;
00350     }
00351 #else /* ? __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00352     // Copy constructor
00353     c_str_VARIANT_proxy_w(class_type const &rhs)
00354         : m_bstr(bstr_dup(rhs.m_bstr))
00355     {}
00356 #endif /* __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00357 
00359     ~c_str_VARIANT_proxy_w()
00360     {
00361         ::SysFreeString(m_bstr);
00362     }
00363 
00364 // Accessors
00365 public:
00367     operator LPCOLESTR () const
00368     {
00369         return (m_bstr == NULL) ? L"" : m_bstr;
00370     }
00371 
00372 // Members
00373 private:
00374     BSTR    m_bstr;
00375 
00376 // Not to be implemented
00377 private:
00378     void operator =(class_type const &rhs);
00379 };
00380 
00384 class c_str_VARIANT_proxy_a
00385 {
00386 public:
00387     typedef c_str_VARIANT_proxy_a   class_type;
00388     typedef c_str_VARIANT_proxy_w   class_w_type;
00389 
00390 // Construction
00391 public:
00395     ss_explicit_k c_str_VARIANT_proxy_a(class_w_type rhs)
00396         : m_proxyw(rhs)
00397         , m_buffer(0)
00398     {}
00399 
00400 #ifdef __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT
00409     c_str_VARIANT_proxy_a(class_type &rhs)
00410         : m_proxyw(rhs.m_proxyw)
00411         , m_buffer(rhs.m_buffer)
00412     {
00413         move_lhs_from_rhs(rhs).m_buffer = NULL;
00414     }
00415 #else /* ? __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00416     // Copy constructor
00417     c_str_VARIANT_proxy_a(class_type const &rhs)
00418         : m_proxyw(rhs.m_proxyw)
00419         , m_buffer(NULL)
00420     {}
00421 #endif /* __STLSOFT_CF_MOVE_CONSTRUCTOR_SUPPORT */
00422 
00424     ~c_str_VARIANT_proxy_a()
00425     {
00426         if(m_buffer != empty_string_())
00427         {
00428             ::CoTaskMemFree(m_buffer);
00429         }
00430     }
00431 
00432 // Accessors
00433 public:
00435     operator cs_char_a_t const *() const
00436     {
00437         if(NULL == m_buffer)
00438         {
00439             LPCOLESTR   w_value     =   m_proxyw;
00440             cs_char_a_t *&buffer_   =   const_cast<class_type*>(this)->m_buffer;
00441 
00442             if( NULL == w_value ||
00443                 L'\0' == *w_value)
00444             {
00445                 buffer_ = empty_string_();
00446             }
00447             else
00448             {
00449                 cs_size_t   cch =   ::SysStringLen((BSTR)w_value);
00450 
00451                 buffer_ = static_cast<cs_char_a_t *>(::CoTaskMemAlloc((1 + cch) * sizeof(cs_char_a_t)));
00452 
00453                 if(NULL == buffer_)
00454                 {
00455                     buffer_ = empty_string_();
00456                 }
00457                 else
00458                 {
00459 #ifdef WIN32
00460                     ::WideCharToMultiByte(0, 0, w_value, -1, buffer_, cch + 1, NULL, NULL);
00461 #else
00462 #error Not currently implemented for operating systems other than Win32
00463 #endif /* __SYNSOFT_DBS_DEBUG */
00464                 }
00465             }
00466         }
00467 
00468         return m_buffer;
00469     }
00470 
00471 // Implementation
00472 private:
00473     static cs_char_a_t *empty_string_()
00474     {
00475         // This character array is initialised to 0, which conveniently happens to
00476         // be the empty string, by the module/application load, so it is
00477         // guaranteed to be valid, and there are no threading/race conditions
00478         static cs_char_a_t  s_empty[1];
00479 
00480         comstl_assert(s_empty[0] == '\0'); // Paranoid check
00481 
00482         return s_empty;
00483     }
00484 
00485 // Members
00486 private:
00487     c_str_VARIANT_proxy_w   m_proxyw;
00488     cs_char_a_t             *m_buffer;
00489 
00490 // Not to be implemented
00491 private:
00492     void operator =(class_type const &rhs);
00493 };
00494 
00495 /* 
00496  * Equivalence testing
00497  */
00498 
00499 // c_str_ptr_GUID_proxy
00500 template <ss_typename_param_k C>
00501 inline cs_bool_t operator ==(C const *lhs, c_str_ptr_GUID_proxy<C> const &rhs)
00502 {
00503     return lhs == static_cast<C const *>(rhs);
00504 }
00505 
00506 template <ss_typename_param_k C>
00507 inline cs_bool_t operator ==(c_str_ptr_GUID_proxy<C> const &lhs, C const *rhs)
00508 {
00509     return static_cast<C const *>(lhs) == rhs;
00510 }
00511 
00512 template <ss_typename_param_k C>
00513 inline cs_bool_t operator !=(C const *lhs, c_str_ptr_GUID_proxy<C> const &rhs)
00514 {
00515     return lhs != static_cast<C const*>(rhs);
00516 }
00517 
00518 template <ss_typename_param_k C>
00519 inline cs_bool_t operator !=(c_str_ptr_GUID_proxy<C> const &lhs, C const *rhs)
00520 {
00521     return static_cast<C const*>(lhs) != rhs;
00522 }
00523 
00524 // c_str_null_VARIANT_proxy
00525 inline cs_bool_t operator ==(LPCOLESTR lhs, c_str_null_VARIANT_proxy const &rhs)
00526 {
00527     return lhs == static_cast<LPCOLESTR>(rhs);
00528 }
00529 
00530 inline cs_bool_t operator ==(c_str_null_VARIANT_proxy const &lhs, LPCOLESTR rhs)
00531 {
00532     return static_cast<LPCOLESTR>(lhs) == rhs;
00533 }
00534 
00535 inline cs_bool_t operator !=(LPCOLESTR lhs, c_str_null_VARIANT_proxy const &rhs)
00536 {
00537     return lhs != static_cast<LPCOLESTR>(rhs);
00538 }
00539 
00540 inline cs_bool_t operator !=(c_str_null_VARIANT_proxy const &lhs, LPCOLESTR rhs)
00541 {
00542     return static_cast<LPCOLESTR>(lhs) != rhs;
00543 }
00544 
00545 // c_str_VARIANT_proxy_a
00546 inline cs_bool_t operator ==(LPCSTR lhs, c_str_VARIANT_proxy_a const &rhs)
00547 {
00548     return lhs == static_cast<LPCSTR>(rhs);
00549 }
00550 
00551 inline cs_bool_t operator ==(c_str_VARIANT_proxy_a const &lhs, LPCSTR rhs)
00552 {
00553     return static_cast<LPCSTR>(lhs) == rhs;
00554 }
00555 
00556 inline cs_bool_t operator !=(LPCSTR lhs, c_str_VARIANT_proxy_a const &rhs)
00557 {
00558     return lhs != static_cast<LPCSTR>(rhs);
00559 }
00560 
00561 inline cs_bool_t operator !=(c_str_VARIANT_proxy_a const &lhs, LPCSTR rhs)
00562 {
00563     return static_cast<LPCSTR>(lhs) != rhs;
00564 }
00565 
00566 // c_str_VARIANT_proxy_w
00567 inline cs_bool_t operator ==(LPCOLESTR lhs, c_str_VARIANT_proxy_w const &rhs)
00568 {
00569     return lhs == static_cast<LPCOLESTR>(rhs);
00570 }
00571 
00572 inline cs_bool_t operator ==(c_str_VARIANT_proxy_w const &lhs, LPCOLESTR rhs)
00573 {
00574     return static_cast<LPCOLESTR>(lhs) == rhs;
00575 }
00576 
00577 inline cs_bool_t operator !=(LPCOLESTR lhs, c_str_VARIANT_proxy_w const &rhs)
00578 {
00579     return lhs != static_cast<LPCOLESTR>(rhs);
00580 }
00581 
00582 inline cs_bool_t operator !=(c_str_VARIANT_proxy_w const &lhs, LPCOLESTR rhs)
00583 {
00584     return static_cast<LPCOLESTR>(lhs) != rhs;
00585 }
00586 
00587 /* 
00588  * IOStream compatibility
00589  */
00590 
00591 template<   ss_typename_param_k C
00592         ,   ss_typename_param_k S
00593         >
00594 inline S &operator <<(S & s, c_str_ptr_GUID_proxy<C> const &shim)
00595 {
00596     s << static_cast<C const*>(shim);
00597 
00598     return s;
00599 }
00600 
00601 template <ss_typename_param_k S>
00602 inline S &operator <<(S & s, c_str_null_VARIANT_proxy const &shim)
00603 {
00604     s << static_cast<LPCOLESTR>(shim);
00605 
00606     return s;
00607 }
00608 
00609 template <ss_typename_param_k S>
00610 inline S &operator <<(S & s, c_str_VARIANT_proxy_w const &shim)
00611 {
00612     s << static_cast<LPCOLESTR>(shim);
00613 
00614     return s;
00615 }
00616 
00617 template <ss_typename_param_k S>
00618 inline S &operator <<(S & s, c_str_VARIANT_proxy_a const &shim)
00619 {
00620     s << static_cast<cs_char_a_t const*>(shim);
00621 
00622     return s;
00623 }
00624 
00625 /* 
00626  * c_str_ptr_null
00627  *
00628  * This can be applied to an expression, and the return value is either a
00629  * pointer to the character string or NULL.
00630  */
00631 
00632 /* GUID */
00634 inline c_str_ptr_GUID_proxy<cs_char_a_t> c_str_ptr_null_a(GUID const &guid)
00635 {
00636     return c_str_ptr_GUID_proxy<cs_char_a_t>(guid);
00637 }
00638 
00640 inline c_str_ptr_GUID_proxy<cs_char_w_t> c_str_ptr_null_w(GUID const &guid)
00641 {
00642     return c_str_ptr_GUID_proxy<cs_char_w_t>(guid);
00643 }
00644 
00646 inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr_null_o(GUID const &guid)
00647 {
00648     return c_str_ptr_GUID_proxy<cs_char_o_t>(guid);
00649 }
00650 
00652 inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr_null(GUID const &guid)
00653 {
00654     return c_str_ptr_null_o(guid);
00655 }
00656 
00657 /* VARIANT */
00659 inline c_str_null_VARIANT_proxy c_str_ptr_null(VARIANT const &v)
00660 {
00661     if(v.vt == VT_BSTR)
00662     {
00663         return c_str_null_VARIANT_proxy(v.bstrVal);
00664     }
00665     else if(v.vt == VT_NULL ||
00666             v.vt == VT_EMPTY)
00667     {
00668         return c_str_null_VARIANT_proxy();
00669     }
00670     else
00671     {
00672         VARIANT vs;
00673         HRESULT hr;
00674 
00675         ::VariantInit(&vs);
00676 
00677         hr  =   ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, 0, VT_BSTR);
00678 
00679         if(FAILED(hr))
00680         {
00681             vs.bstrVal = NULL;
00682         }
00683 
00684         return c_str_null_VARIANT_proxy(&vs.bstrVal);
00685     }
00686 }
00687 
00688 /* 
00689  * c_str_ptr
00690  *
00691  * This can be applied to an expression, and the return value is either a
00692  * pointer to the character string or to an empty string.
00693  */
00694 
00695 /* GUID */
00697 inline c_str_ptr_GUID_proxy<cs_char_a_t> c_str_ptr_a(GUID const &guid)
00698 {
00699     return c_str_ptr_GUID_proxy<cs_char_a_t>(guid);
00700 }
00701 
00703 inline c_str_ptr_GUID_proxy<cs_char_w_t> c_str_ptr_w(GUID const &guid)
00704 {
00705     return c_str_ptr_GUID_proxy<cs_char_w_t>(guid);
00706 }
00707 
00709 inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr_o(GUID const &guid)
00710 {
00711     return c_str_ptr_GUID_proxy<cs_char_o_t>(guid);
00712 }
00713 
00715 inline c_str_ptr_GUID_proxy<cs_char_o_t> c_str_ptr(GUID const &guid)
00716 {
00717     return c_str_ptr_o(guid);
00718 }
00719 
00720 /* VARIANT */
00722 inline c_str_VARIANT_proxy_a c_str_ptr_a(VARIANT const &v)
00723 {
00724     VARIANT vs;
00725     HRESULT hr;
00726 
00727     ::VariantInit(&vs);
00728 
00729     hr  =   ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, 0, VT_BSTR);
00730 
00731     if(FAILED(hr))
00732     {
00733         vs.bstrVal = NULL;
00734     }
00735 
00736     return c_str_VARIANT_proxy_a(c_str_VARIANT_proxy_w(vs.bstrVal));
00737 }
00738 
00740 inline c_str_VARIANT_proxy_w c_str_ptr_w(VARIANT const &v)
00741 {
00742     VARIANT vs;
00743     HRESULT hr;
00744 
00745     ::VariantInit(&vs);
00746 
00747     hr  =   ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, VARIANT_ALPHABOOL, VT_BSTR);
00748 
00749     if(FAILED(hr))
00750     {
00751         vs.bstrVal = NULL;
00752     }
00753 
00754     return c_str_VARIANT_proxy_w(vs.bstrVal);
00755 }
00756 
00758 inline c_str_VARIANT_proxy_w c_str_ptr(VARIANT const &v)
00759 {
00760     return c_str_ptr_w(v);
00761 }
00762 
00763 /* 
00764  * c_str_len
00765  *
00766  * This can be applied to an expression, and the return value is the number of
00767  * characters in the character string in the expression.
00768  */
00769 
00770 /* GUID */
00772 inline cs_size_t c_str_len_a(GUID const &/* guid */)
00773 {
00774     return COMSTL_CCH_GUID;
00775 }
00776 
00778 inline cs_size_t c_str_len_w(GUID const &/* guid */)
00779 {
00780     return COMSTL_CCH_GUID;
00781 }
00782 
00784 inline cs_size_t c_str_len_o(GUID const &/* guid */)
00785 {
00786     return COMSTL_CCH_GUID;
00787 }
00788 
00790 inline cs_size_t c_str_len(GUID const &/* guid */)
00791 {
00792     return COMSTL_CCH_GUID;
00793 }
00794 
00795 /* VARIANT */
00797 inline cs_size_t c_str_len(VARIANT const &v)
00798 {
00799     cs_size_t   len;
00800 
00801     if(v.vt == VT_BSTR)
00802     {
00803         len = v.bstrVal != NULL ? ::SysStringLen(v.bstrVal) : 0;
00804     }
00805     else if(v.vt == VT_NULL ||
00806             v.vt == VT_EMPTY)
00807     {
00808         len = 0;
00809     }
00810     else
00811     {
00812         VARIANT     vs;
00813         HRESULT     hr;
00814 
00815         ::VariantInit(&vs);
00816 
00817         hr  =   ::VariantChangeTypeEx(&vs, const_cast<VARIANT *>(&v), LOCALE_USER_DEFAULT, 0, VT_BSTR);
00818 
00819         if(FAILED(hr))
00820         {
00821             len = 0;
00822         }
00823         else
00824         {
00825             len = vs.bstrVal ? ::SysStringLen(vs.bstrVal) : 0;
00826 
00827             ::VariantClear(&vs);
00828         }
00829     }
00830 
00831     return len;
00832 }
00833 
00835 inline cs_size_t c_str_len_a(VARIANT const &v)
00836 {
00837     return c_str_len(v);
00838 }
00839 
00841 inline cs_size_t c_str_len_w(VARIANT const &v)
00842 {
00843     return c_str_len(v);
00844 }
00845 
00846 /* 
00847  * c_str_size
00848  *
00849  * This can be applied to an expression, and the return value is the number of
00850  * bytes required to store the character string in the expression, NOT including
00851  * the null-terminating character.
00852  */
00853 
00854 /* GUID */
00856 inline cs_size_t c_str_size_a(GUID const &guid)
00857 {
00858     return c_str_len_a(guid) *sizeof(cs_char_a_t);
00859 }
00860 
00862 inline cs_size_t c_str_size_w(GUID const &guid)
00863 {
00864     return c_str_len_w(guid) * sizeof(cs_char_w_t);
00865 }
00866 
00868 inline cs_size_t c_str_size_o(GUID const &guid)
00869 {
00870     return c_str_len_o(guid) * sizeof(cs_char_o_t);
00871 }
00872 
00874 inline cs_size_t c_str_size(GUID const &guid)
00875 {
00876     return c_str_size_o(guid);
00877 }
00878 
00879 /* VARIANT */
00881 inline cs_size_t c_str_size_a(VARIANT const &v)
00882 {
00883     return c_str_len(v) * sizeof(cs_char_a_t);
00884 }
00885 
00887 inline cs_size_t c_str_size_w(VARIANT const &v)
00888 {
00889     return c_str_len(v) * sizeof(OLECHAR);
00890 }
00891 
00893 inline cs_size_t c_str_size(VARIANT const &v)
00894 {
00895     return c_str_size_w(v);
00896 }
00897 
00899 // Unit-testing
00900 
00901 #ifdef STLSOFT_UNITTEST
00902 
00903 namespace unittest
00904 {
00905     namespace
00906     {
00907         ss_bool_t test_comstl_string_access_GUID(unittest_reporter *r)
00908         {
00909             ss_bool_t   bSuccess = true;
00910 
00911             /* Check GUID conversion */
00912             GUID const  guid    =   GUID_NULL;
00913 
00914             if(0 != wcscmp(c_str_ptr(guid), L"{00000000-0000-0000-0000-000000000000}"))
00915             {
00916                 r->report("c_str_ptr(GUID) failed ", __LINE__);
00917                 bSuccess = false;
00918             }
00919 
00920             if(0 != wcscmp(c_str_ptr_null(guid), L"{00000000-0000-0000-0000-000000000000}"))
00921             {
00922                 r->report("c_str_ptr_null(GUID) failed ", __LINE__);
00923                 bSuccess = false;
00924             }
00925 
00926             if(COMSTL_CCH_GUID != c_str_len(guid))
00927             {
00928                 r->report("c_str_len(GUID) failed ", __LINE__);
00929                 bSuccess = false;
00930             }
00931 
00932             return bSuccess;
00933         }
00934 
00935         ss_bool_t test_comstl_string_access_VARIANT(unittest_reporter *r)
00936         {
00937             ss_bool_t   bSuccess = true;
00938 
00939             /* Check VARIANT conversion */
00940             VARIANT     var1;
00941 
00942             ::VariantInit(&var1);
00943             var1.vt     =   VT_I4;
00944             var1.lVal   =   1968;
00945 
00946             if(0 != wcscmp(L"1968", c_str_ptr(var1)))
00947             {
00948                 r->report("c_str_ptr(VARIANT) failed ", __LINE__);
00949                 bSuccess = false;
00950             }
00951 
00952             if(0 != wcscmp(L"1968", c_str_ptr_null(var1)))
00953             {
00954                 r->report("c_str_ptr_null(VARIANT) failed ", __LINE__);
00955                 bSuccess = false;
00956             }
00957 
00958             VARIANT     var2;
00959 
00960             ::VariantInit(&var1);
00961 
00962             if(0 != wcscmp(L"", c_str_ptr(var2)))
00963             {
00964                 r->report("c_str_ptr(VARIANT) failed ", __LINE__);
00965                 bSuccess = false;
00966             }
00967 
00968             if(NULL != c_str_ptr_null(var2))
00969             {
00970                 r->report("c_str_ptr_null(VARIANT) failed ", __LINE__);
00971                 bSuccess = false;
00972             }
00973 
00974             return bSuccess;
00975         }
00976 
00977     } // anonymous namespace
00978 
00979     ss_bool_t test_comstl_string_access(unittest_reporter *r)
00980     {
00981         using stlsoft::unittest::unittest_initialiser;
00982 
00983         ss_bool_t               bSuccess    =   true;
00984 
00985         unittest_initialiser    init(r, "COMSTL", "string_access", __FILE__);
00986 
00987         // 1. Test GUID
00988         if(bSuccess)
00989         {
00990             bSuccess = test_comstl_string_access_GUID(r);
00991         }
00992 
00993         // 1. Test CWindow
00994         if(bSuccess)
00995         {
00996             bSuccess = test_comstl_string_access_VARIANT(r);
00997         }
00998 
00999         return bSuccess;
01000     }
01001 
01002     unittest_registrar    unittest_comstl_string_access(test_comstl_string_access);
01003 
01004 } // namespace unittest
01005 
01006 #endif /* STLSOFT_UNITTEST */
01007 
01008 /* 
01009 
01011 
01012 /* 
01013 
01014 #ifndef _COMSTL_NO_NAMESPACE
01015 # if defined(_STLSOFT_NO_NAMESPACE) || \
01016      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
01017 } // namespace comstl
01018 # else
01019 } // namespace stlsoft::comstl_project
01020 } // namespace stlsoft
01021 # endif /* _STLSOFT_NO_NAMESPACE */
01022 #endif /* !_COMSTL_NO_NAMESPACE */
01023 
01024 /* 
01025  * Namespace
01026  *
01027  * The string access shims exist either in the stlsoft namespace, or in the
01028  * global namespace. This is required by the lookup rules.
01029  *
01030  */
01031 
01032 #ifndef _COMSTL_NO_NAMESPACE
01033 # if !defined(_STLSOFT_NO_NAMESPACE) && \
01034      !defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
01035 namespace stlsoft
01036 {
01037 # else /* ? _STLSOFT_NO_NAMESPACE */
01038 /* There is no stlsoft namespace, so must define in the global namespace */
01039 # endif /* !_STLSOFT_NO_NAMESPACE */
01040 
01041 using ::comstl::c_str_ptr_null_a;
01042 using ::comstl::c_str_ptr_null_w;
01043 using ::comstl::c_str_ptr_null_o;
01044 using ::comstl::c_str_ptr_null;
01045 
01046 using ::comstl::c_str_ptr_a;
01047 using ::comstl::c_str_ptr_w;
01048 using ::comstl::c_str_ptr_o;
01049 using ::comstl::c_str_ptr;
01050 
01051 using ::comstl::c_str_len_a;
01052 using ::comstl::c_str_len_w;
01053 using ::comstl::c_str_len_o;
01054 using ::comstl::c_str_len;
01055 
01056 using ::comstl::c_str_size_a;
01057 using ::comstl::c_str_size_w;
01058 using ::comstl::c_str_size_o;
01059 using ::comstl::c_str_size;
01060 
01061 # if !defined(_STLSOFT_NO_NAMESPACE) && \
01062      !defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
01063 } // namespace stlsoft
01064 # else /* ? _STLSOFT_NO_NAMESPACE */
01065 /* There is no stlsoft namespace, so must define in the global namespace */
01066 # endif /* !_STLSOFT_NO_NAMESPACE */
01067 #endif /* !_COMSTL_NO_NAMESPACE */
01068 
01069 /* 
01070 
01071 #endif /* !COMSTL_INCL_H_COMSTL_STRING_ACCESS */
01072 
01073 /* 

STLSoft Libraries documentation © Synesis Software Pty Ltd, 2001-2004