bstr.h

Go to the documentation of this file.
00001 00004 /* 00005 * Copyright © 2000-2004 Sofus Mortensen, Michael Geddes 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_BSTR_H 00020 #define COMET_BSTR_H 00021 00022 #include <comet/config.h> 00023 00024 #ifdef COMET_BROKEN_WTYPES 00025 #include <windows.h> 00026 #endif // COMET_BROKEN_WTYPES 00027 #include <wtypes.h> 00028 #include <malloc.h> 00029 #include <stdexcept> 00030 #ifndef COMET_GCC_HEADERS 00031 #include <oleauto.h> 00032 #endif // COMET_GCC_HEADERS 00033 00034 #include <string> 00035 #include <functional> 00036 #ifndef NDEBUG 00037 #include <limits.h> 00038 #endif // NDEBUG 00039 #include <comet/assert.h> 00040 #include <comet/common.h> 00041 #include <comet/static_assert.h> 00042 #include <comet/error_fwd.h> 00043 #include <comet/uuid_fwd.h> 00044 #include <comet/currency.h> 00045 #include <comet/type_traits.h> 00046 00047 #pragma warning(push) 00048 #pragma warning(disable : 4522 4521) 00049 00050 #pragma comment( lib, "oleaut32" ) 00051 00052 namespace comet { 00053 00054 class datetime_t; 00055 class currency_t; 00056 template<typename T> class com_ptr; 00057 template<typename T> class safearray_t; 00058 00059 // Forward declaration 00060 // class variant_t; 00061 00062 #ifndef NORM_IGNOREKASHIDA 00063 #define NORM_IGNOREKASHIDA 0x00040000 00064 #endif // NORM_IGNOREKASHIDA 00065 00068 00069 00079 enum compare_flags_t 00080 { 00081 cf_ignore_case = NORM_IGNORECASE, 00082 cf_ingore_nonspace = NORM_IGNORENONSPACE, 00083 cf_ignore_symbols = NORM_IGNORESYMBOLS, 00084 cf_ignore_width = NORM_IGNOREWIDTH, 00085 cf_ignore_kanatype = NORM_IGNOREKANATYPE, 00086 cf_ignore_kashida = NORM_IGNOREKASHIDA 00087 }; 00089 00090 namespace impl { 00091 00092 inline const wchar_t* null_to_empty(const wchar_t* s) 00093 { return s ? s : L""; } 00094 00095 } // namespace 00096 00097 00101 00106 class bstr_t { 00107 public: 00108 typedef wchar_t value_type; 00109 #ifndef _STLP_DEBUG 00110 typedef std::wstring::iterator iterator; 00111 typedef std::wstring::const_iterator const_iterator; 00112 00113 typedef std::wstring::reverse_iterator reverse_iterator; 00114 typedef std::wstring::const_reverse_iterator const_reverse_iterator; 00115 #else // _STLP_DEBUG 00116 typedef wchar_t *iterator; 00117 typedef const wchar_t *const_iterator; 00118 #if defined(COMET_STD_ITERATOR) 00119 typedef std::reverse_iterator<iterator> reverse_iterator; 00120 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00121 #else 00122 // workaround for broken reverse_iterator implementations due to no partial specialisation 00123 typedef std::reverse_iterator<iterator,wchar_t> reverse_iterator; 00124 typedef std::reverse_iterator<const_iterator,wchar_t> const_reverse_iterator; 00125 #endif 00126 #endif // _STLP_DEBUG 00127 00128 typedef std::wstring::size_type size_type; 00129 typedef std::wstring::difference_type difference_type; 00130 00131 typedef wchar_t& reference; 00132 typedef const wchar_t const_reference; 00133 00134 private: 00135 BSTR str_; 00136 00137 void construct() { str_ = 0; } 00138 void construct(BSTR s, bool copy) throw(std::bad_alloc) 00139 { if (copy) str_ = copy_str(s); else str_ = s; } 00140 00141 void construct(const wchar_t* s) throw(std::bad_alloc) 00142 { str_ = copy_str(s); } 00143 00144 void construct(const wchar_t* s, size_t len) throw(std::bad_alloc) 00145 { str_ = copy_str(s, len); } 00146 00147 void construct(const char* s) throw(std::bad_alloc, std::runtime_error) { 00148 convert_str(s, -1); 00149 } 00150 00151 void construct(const char* s, size_t len) throw(std::bad_alloc, std::runtime_error) { 00152 COMET_ASSERT( len <= INT_MAX ); 00153 convert_str(s, static_cast<int>(len+1)); 00154 } 00155 00156 void construct(const uuid_t& u, bool braces) 00157 { 00158 str_ = impl::bad_alloc_check(::SysAllocStringLen(0, braces?38:36)); 00159 u.copy_to_str(str_+(braces?1:0)); 00160 if (braces) 00161 { 00162 str_[0]=L'{'; 00163 str_[37]=L'}'; 00164 } 00165 } 00166 00167 void construct(const wchar_t* s1, size_t l1, const wchar_t* s2, size_t l2) throw(std::bad_alloc) 00168 { 00169 str_ = impl::bad_alloc_check(::SysAllocStringLen(NULL, UINT(l1+l2))); 00170 if (l1) memcpy(str_, s1, sizeof(wchar_t)*(l1)); 00171 if (l2) memcpy(str_+l1, s2, sizeof(wchar_t)*(1+l2)); 00172 } 00173 00174 void destroy() throw() 00175 { if (str_) ::SysFreeString(str_); } 00176 00177 bool is_regular() const throw() 00178 { return !str_ || length() == wcslen(str_); } 00179 00180 static BSTR copy_str(const wchar_t* src) throw(std::bad_alloc) 00181 { return src ? impl::bad_alloc_check(::SysAllocString(src)) : 0; } 00182 00183 static BSTR copy_str(const wchar_t* src, size_t len) throw(std::bad_alloc) 00184 { return src ? impl::bad_alloc_check(::SysAllocStringLen(src, UINT(len))) : 0; } 00185 00186 static BSTR copy_str(BSTR src) throw(std::bad_alloc) 00187 { return src ? impl::bad_alloc_check(::SysAllocStringLen(src, ::SysStringLen(src))) : 0; } 00188 00189 void convert_str(const char* s, int l) throw(std::bad_alloc, std::runtime_error) 00190 { 00191 if (s != 0) { 00192 #if defined(_MBCS) || !defined(COMET_NO_MBCS) 00193 size_t wl = ::MultiByteToWideChar(CP_ACP, 0, s, l, NULL,0); 00194 #else 00195 size_t wl = ((l>=0)?l: (1+strlen(s))); 00196 COMET_ASSERT( wl == ::MultiByteToWideChar( CP_ACP, 0, s, l, NULL,0)); 00197 #endif 00198 str_ = impl::bad_alloc_check(::SysAllocStringLen(0, UINT(wl-1))); 00199 if (::MultiByteToWideChar(CP_ACP, 0, s, l, str_, wl) == 0) 00200 { 00201 destroy(); 00202 throw std::runtime_error("MultiByteToWideChar has failed"); 00203 } 00204 } else str_ = 0; 00205 } 00206 00207 public: 00211 bstr_t() throw() 00212 { 00213 construct(); 00214 } 00215 00217 00224 bstr_t(const bstr_t& s) throw(std::bad_alloc) 00225 { 00226 construct(s.str_, true); 00227 } 00228 00230 00237 bstr_t(const wchar_t* s) throw(std::bad_alloc) 00238 { 00239 construct(s); 00240 } 00241 00242 bstr_t(const wchar_t* s, size_t len) throw(std::bad_alloc) 00243 { 00244 construct(s, len); 00245 } 00246 00248 00257 bstr_t(const char* s) throw(std::runtime_error) 00258 { 00259 construct(s); 00260 } 00261 00262 bstr_t(const char* s, size_t len) throw(std::bad_alloc) 00263 { 00264 construct(s, len); 00265 } 00266 00268 00277 bstr_t(const std::string& s) throw(std::runtime_error) 00278 { 00279 construct(s.c_str(), s.length()); 00280 } 00281 00283 00293 bstr_t(const impl::auto_attach_t<BSTR>& s) throw() 00294 { 00295 construct(s.get(), false); 00296 } 00297 00298 00300 00307 bstr_t(const std::wstring& s) throw(std::bad_alloc) 00308 { 00309 construct(s.c_str(), s.length()); 00310 } 00311 00312 explicit bstr_t(size_type sz, wchar_t c) throw(std::bad_alloc) 00313 { 00314 str_ = impl::bad_alloc_check(::SysAllocStringLen(0, UINT(sz))); 00315 std::fill(begin(), end(), c); 00316 } 00317 00318 explicit bstr_t(size_type sz) throw(std::bad_alloc) 00319 { 00320 str_ = impl::bad_alloc_check(::SysAllocStringLen(0, UINT(sz))); 00321 } 00322 00323 template<typename IT> 00324 explicit bstr_t(IT first, IT last) 00325 { 00326 str_ = 0; 00327 assign(first, last); 00328 } 00329 00330 // bstr_t(const variant_t& v) throw(std::bad_alloc); 00331 00332 explicit bstr_t(const uuid_t& u, bool braces = false) 00333 { 00334 construct(u, braces); 00335 } 00336 00337 private: 00338 bstr_t(const wchar_t* s1, size_t l1, const wchar_t* s2, size_t l2) throw(std::bad_alloc) 00339 { 00340 construct(s1, l1, s2, l2); 00341 } 00342 00343 public: 00345 00348 ~bstr_t() throw() 00349 { 00350 destroy(); 00351 } 00352 00354 void swap(bstr_t& x) throw() 00355 { 00356 std::swap(str_, x.str_); 00357 } 00358 00359 00361 const wchar_t* c_str() const throw() 00362 { return impl::null_to_empty(str_); } 00363 00365 std::wstring w_str() const throw() 00366 { return impl::null_to_empty(str_); } 00367 00368 #ifdef _MBCS 00369 #ifndef COMET_NO_MBCS_WARNING 00370 #pragma message( "Warning: _MBCS is defined. bstr_t::s_str may return an std::string containing multibyte characters" ) 00371 #endif 00372 #endif 00373 00375 std::string s_str() const 00376 { 00377 if (is_empty()) return std::string(); 00378 00379 size_t ol = length()+1; 00380 #if defined(_MBCS) || !defined(COMET_NO_MBCS) 00381 // Calculate the required length of the buffer 00382 size_t l = WideCharToMultiByte(CP_ACP, 0, str_, ol , NULL, 0, NULL, NULL); 00383 #else // _MBCS 00384 size_t l = ol; 00385 COMET_ASSERT( l == WideCharToMultiByte(CP_ACP, 0, str_, ol , NULL, 0, NULL, NULL)); 00386 #endif // _MBCS 00387 00388 // Create the buffer 00389 std::string rv(l-1, ' '); 00390 // Do the conversion. 00391 if (0 == WideCharToMultiByte(CP_ACP, 0, str_, UINT(ol), &rv[0], UINT(l), NULL, NULL)) { 00392 DWORD err = GetLastError(); 00393 raise_exception(HRESULT_FROM_WIN32(err)); 00394 } 00395 // remove trailing zero 00396 //rv.erase(l-1); 00397 return rv; 00398 } 00399 00401 #ifdef _UNICODE 00402 std::wstring t_str() const 00403 { 00404 return w_str(); 00405 } 00406 #else 00407 std::string t_str() const 00408 { 00409 return s_str(); 00410 } 00411 #endif 00412 00414 operator std::wstring() const { return w_str(); } 00415 00417 operator std::string() const { return s_str(); } 00418 00420 bool is_null() const throw() 00421 { return str_ == 0; } 00422 00425 bool is_empty() const throw() { return length() == 0; } 00426 00428 bool empty() const throw() { return length() == 0; } 00429 00431 size_t length() const throw() 00432 { return is_null() ? 0 : ::SysStringLen(str_); } 00433 00434 size_t size() const throw() 00435 { return length(); } 00436 00438 BSTR get_raw() const 00439 { return str_; } 00440 00441 friend 00442 std::basic_ostream<char> &operator<<(std::basic_ostream<char> &os, const bstr_t &val) 00443 { os << val.s_str(); return os; } 00444 00445 friend 00446 std::basic_ostream<wchar_t> &operator<<(std::basic_ostream<wchar_t> &os, const bstr_t &val) 00447 { os << val.w_str(); return os; } 00448 00450 00451 00452 /* bool operator!=(const variant_t&) const; 00453 bool operator==(const variant_t&) const; 00454 bool operator<(const variant_t&) const; 00455 bool operator>(const variant_t&) const; 00456 bool operator<=(const variant_t&) const; 00457 bool operator>=(const variant_t&) const; 00458 */ 00459 bool operator==(const wchar_t* s) const 00460 { return 0 == wcscmp(c_str(), impl::null_to_empty(s) ) && is_regular(); } 00461 00462 bool operator!=(const wchar_t* s) const 00463 { return !operator==(s); } 00464 00465 bool operator<(const wchar_t* s) const 00466 { return wcscmp(c_str(), impl::null_to_empty(s)) < 0 && is_regular(); } 00467 00468 bool operator>(const wchar_t* s) const 00469 { return wcscmp(c_str(), impl::null_to_empty(s)) > 0 && !is_regular(); } 00470 00471 bool operator>=(const wchar_t* s) const 00472 { return !operator<(s); } 00473 00474 bool operator<=(const wchar_t* s) const 00475 { return !operator>(s); } 00476 00477 bool operator==(const std::wstring& s) const 00478 { 00479 size_t l = length(); 00480 if (l != s.length()) return false; 00481 return 0 == memcmp(str_, s.c_str(), sizeof(wchar_t)*l); 00482 } 00483 00484 bool operator!=(const std::wstring& s) const 00485 { return !operator==(s); } 00486 00487 bool operator<(const std::wstring& s) const 00488 { return std::lexicographical_compare(str_, str_+length(), s.begin(), s.end()); } 00489 00490 bool operator>(const std::wstring& s) const 00491 { return std::lexicographical_compare(str_, str_+length(), s.begin(), s.end(), std::greater<wchar_t>()); } 00492 00493 bool operator>=(const std::wstring& s) const 00494 { return !operator<(s); } 00495 00496 bool operator<=(const std::wstring& s) const 00497 { return !operator>(s); } 00498 00499 bool operator==(const bstr_t& s) const 00500 { 00501 if (str_ == 0 && s.str_ == 0) return true; 00502 return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_EQ; 00503 } 00504 00505 bool operator!=(const bstr_t& s) const 00506 { return !operator==(s); } 00507 00508 bool operator<(const bstr_t& s) const 00509 { 00510 if (str_ == 0) { 00511 return s.str_ != 0; 00512 } 00513 00514 if (s.str_ == 0) return false; 00515 00516 return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_LT; 00517 } 00518 00519 bool operator>(const bstr_t& s) const 00520 { 00521 if (str_ == 0) { 00522 return s.str_ != 0; 00523 } 00524 00525 if (s.str_ == 0) return false; 00526 00527 return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_GT; 00528 } 00529 00530 bool operator>=(const bstr_t& s) const 00531 { return !operator<(s); } 00532 00533 bool operator<=(const bstr_t& s) const 00534 { return !operator>(s); } 00536 00538 00544 int cmp(const bstr_t& s, compare_flags_t flags = compare_flags_t(0)) const 00545 { 00546 HRESULT res = ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), flags); 00547 switch(res) 00548 { 00549 case VARCMP_EQ: return 0; 00550 case VARCMP_GT: return 1; 00551 case VARCMP_LT: return -1; 00552 case VARCMP_NULL: 00553 return ((str_==0)?0:1) - ((s.str_==0)?0:1); 00554 } 00555 if (str_==0 || s.str_ ==0) 00556 return ((str_==0)?0:1) - ((s.str_==0)?0:1); 00557 raise_exception(res); return 0; 00558 } 00559 00560 // //!\name Comparison Functors 00561 // //@{ 00563 00570 template<compare_flags_t CF> 00571 struct less : std::binary_function< bstr_t,bstr_t,bool>{ 00573 bool operator()(const bstr_t& l, const bstr_t& r) const 00574 { return l.cmp(r, CF) <0; } 00575 }; 00576 00578 00579 template<compare_flags_t CF> 00580 struct less_equal : std::binary_function< bstr_t,bstr_t,bool> { 00582 bool operator()(const bstr_t& l, const bstr_t& r) const 00583 { return l.cmp(r, CF) <=0; } 00584 }; 00585 00587 00588 template<compare_flags_t CF> 00589 struct greater : std::binary_function< bstr_t,bstr_t,bool> { 00591 bool operator()(const bstr_t& l, const bstr_t& r) const 00592 { return l.cmp(r, CF) > 0; } 00593 }; 00594 00596 00597 template<compare_flags_t CF> 00598 struct greater_equal : std::binary_function< bstr_t,bstr_t,bool> { 00600 bool operator()(const bstr_t& l, const bstr_t& r) const 00601 { return l.cmp(r, CF) >=0; } 00602 }; 00603 00605 template<compare_flags_t CF> 00606 struct equal_to : std::binary_function< bstr_t,bstr_t,bool> { 00607 bool operator()(const bstr_t& l, const bstr_t& r) const 00608 { return l.cmp(r, CF) == 0; } 00609 }; 00610 00612 00613 template<compare_flags_t CF> 00614 struct not_equal_to : std::binary_function< bstr_t,bstr_t,bool>{ 00616 bool operator()(const bstr_t& l, const bstr_t& r) const 00617 { return l.cmp(r, CF) != 0; } 00618 }; 00619 // //@} 00620 00621 iterator begin() { return iterator(str_); } 00622 iterator end() { return iterator(str_ + length()); } 00623 const_iterator begin() const { return const_iterator(str_); } 00624 const_iterator end() const { return const_iterator(str_ + length()); } 00625 00626 reverse_iterator rbegin() { return reverse_iterator(str_); } 00627 reverse_iterator rend() { return reverse_iterator(str_ + length()); } 00628 const_reverse_iterator rbegin() const { return const_reverse_iterator(str_); } 00629 const_reverse_iterator rend() const { return const_reverse_iterator(str_ + length()); } 00630 00631 reference at(size_type i) { rangecheck(i); return str_[i]; } 00632 const_reference at(size_type i) const { rangecheck(i); return str_[i]; } 00633 00634 private: 00635 // check range (may be private because it is static) 00636 void rangecheck (size_type i) const { 00637 if (i >= length()) { throw std::range_error("bstr_t"); } 00638 } 00639 00640 public: 00641 const_reference operator[](size_type idx) const 00642 { return str_[idx]; } 00643 00644 reference operator[](size_type idx) 00645 { return str_[idx]; } 00646 00648 void assign(size_type sz, wchar_t c) throw(std::bad_alloc) 00649 { 00650 bstr_t t(sz, c); 00651 swap(t); 00652 } 00653 00655 template<typename IT> 00656 void assign(IT first, IT last) 00657 { 00658 bstr_t t( std::distance(first, last) ); 00659 std::copy(first, last, t.begin()); 00660 swap(t); 00661 } 00662 00663 00665 template<typename T> 00666 bstr_t& operator=(const T& x) 00667 { 00668 COMET_STATIC_ASSERT( type_traits::is_integer<T>::result == false ); 00669 bstr_t t(x); 00670 swap(t); 00671 return *this; 00672 } 00673 00675 bstr_t& operator=(const bstr_t& x) throw(std::bad_alloc) 00676 { 00677 bstr_t t(x); 00678 swap(t); 00679 return *this; 00680 } 00681 00683 bstr_t operator+(const bstr_t& s) const throw(std::bad_alloc) 00684 { 00685 return bstr_t(str_, length(), s.str_, s.length()); 00686 } 00687 00689 bstr_t operator+(const wchar_t* s) const throw(std::bad_alloc) 00690 { 00691 return bstr_t(str_, length(), s, wcslen(s)); 00692 } 00693 00695 bstr_t operator+(const std::wstring& s) const throw(std::bad_alloc) 00696 { 00697 return bstr_t(str_, length(), s.c_str(), s.length()); 00698 } 00699 00701 bstr_t& operator+=(const bstr_t& s) throw(std::bad_alloc) 00702 { 00703 bstr_t t(str_, length(), s.str_, s.length()); 00704 swap(t); 00705 return *this; 00706 } 00707 00709 bstr_t& operator+=(const wchar_t* s) throw(std::bad_alloc) 00710 { 00711 bstr_t t(str_, length(), s, wcslen(s)); 00712 swap(t); 00713 return *this; 00714 } 00715 00717 bstr_t& operator+=(const std::wstring& s) throw(std::bad_alloc) 00718 { 00719 bstr_t t(str_, length(), s.c_str(), s.length()); 00720 swap(t); 00721 return *this; 00722 } 00723 00724 private: 00726 BSTR detach() 00727 { 00728 BSTR s(str_); 00729 str_ = 0; 00730 return s; 00731 } 00732 public: 00733 00735 00742 static const bstr_t& create_const_reference(const BSTR& s) throw() 00743 { return *reinterpret_cast<const bstr_t*>(&s); } 00744 00745 static bstr_t& create_reference(BSTR& s) throw() 00746 { return *reinterpret_cast<bstr_t*>(&s); } 00748 00750 static BSTR detach(bstr_t& s) 00751 { 00752 return s.detach(); 00753 } 00754 00756 template<typename T> 00757 static BSTR detach(const T& s) 00758 { 00759 return bstr_t(s).detach(); 00760 } 00761 00763 BSTR* get_ptr_to_raw() const 00764 { 00765 return const_cast<BSTR*>(&str_); 00766 } 00767 00769 00779 BSTR in() const throw() 00780 { 00781 return str_; 00782 } 00783 00785 00795 BSTR* in_ptr() const throw() 00796 { 00797 return const_cast<BSTR*>(&str_); 00798 } 00799 00801 00811 BSTR* out() throw() 00812 { 00813 destroy(); 00814 return &str_; 00815 } 00816 00818 00833 BSTR* inout() throw(std::bad_alloc) 00834 { 00835 return &str_; 00836 } 00837 00838 friend bstr_t operator+(const std::wstring& s, const bstr_t& t) throw(std::bad_alloc); 00839 friend bstr_t operator+(const wchar_t* s, const bstr_t& t) throw(std::bad_alloc); 00840 }; 00841 00843 inline bstr_t operator+(const std::wstring& s, const bstr_t& t) throw(std::bad_alloc) 00844 { 00845 return bstr_t(s.c_str(), s.length(), t.str_, t.length()); 00846 } 00847 00849 inline bstr_t operator+(const wchar_t* s, const bstr_t& t) throw(std::bad_alloc) 00850 { 00851 return bstr_t(s, wcslen(s), t.str_, t.length()); 00852 } 00854 00859 inline bool operator==(const wchar_t* s1, const bstr_t& s2) throw() 00860 { 00861 return s2 == s1; 00862 } 00863 00864 inline bool operator!=(const wchar_t* s1, const bstr_t& s2) throw() 00865 { 00866 return s2 != s1; 00867 } 00868 00869 inline bool operator<(const wchar_t* s1, const bstr_t& s2) throw() 00870 { 00871 return s2 > s1; 00872 } 00873 00874 inline bool operator>(const wchar_t* s1, const bstr_t& s2) throw() 00875 { 00876 return s2 < s1; 00877 } 00878 00879 inline bool operator<=(const wchar_t* s1, const bstr_t& s2) throw() 00880 { 00881 return s2 >= s1; 00882 } 00883 00884 inline bool operator>=(const wchar_t* s1, const bstr_t& s2) throw() 00885 { 00886 return s2 <= s1; 00887 } 00888 00889 inline bool operator==(const std::wstring& s1, const bstr_t& s2) throw() 00890 { 00891 return s2 == s1; 00892 } 00893 00894 inline bool operator!=(const std::wstring& s1, const bstr_t& s2) throw() 00895 { 00896 return s2 != s1; 00897 } 00898 00899 inline bool operator<(const std::wstring& s1, const bstr_t& s2) throw() 00900 { 00901 return s2 > s1; 00902 } 00903 00904 inline bool operator>(const std::wstring& s1, const bstr_t& s2) throw() 00905 { 00906 return s2 < s1; 00907 } 00908 00909 inline bool operator<=(const std::wstring& s1, const bstr_t& s2) throw() 00910 { 00911 return s2 >= s1; 00912 } 00913 00914 inline bool operator>=(const std::wstring& s1, const bstr_t& s2) throw() 00915 { 00916 return s2 <= s1; 00917 } 00919 00920 00921 // Implementation of uuid_t construct from bstr. 00922 inline uuid_t::uuid_t(const bstr_t& bs) 00923 { 00924 if (init_from_str(bs.c_str(), bs.length()) == false) throw std::runtime_error(err_msg()); 00925 } 00926 00927 inline currency_t& currency_t::parse( const bstr_t &str, LCID locale ) 00928 { 00929 VarCyFromStr( str.in(), locale, 0, &cy_ ) | raise_exception; 00930 return *this; 00931 } 00932 00933 } // namespace 00934 00935 namespace { 00936 COMET_STATIC_ASSERT( sizeof(comet::bstr_t) == sizeof(BSTR) ); 00937 COMET_STATIC_ASSERT( sizeof(comet::bstr_t) == sizeof(BSTR) ); 00938 } 00939 00940 namespace std { 00941 template<> inline void swap( comet::bstr_t& x, comet::bstr_t& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 00942 } 00943 00944 #include <comet/variant.h> 00945 #include <comet/uuid.h> 00946 00947 #pragma warning(pop) 00948 00949 #endif /* COMET_BSTR_H */