- Timestamp:
- Mar 25, 2011 12:46:45 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/string.h
r35128 r36428 58 58 /** 59 59 * String class used universally in Main for COM-style Utf-16 strings. 60 * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions 61 * back and forth since most of VirtualBox and our libraries use UTF-8. 62 * 63 * To make things more obscure, on Windows, a COM-style BSTR is not just a 64 * pointer to a null-terminated wide character array, but the four bytes 65 * (32 bits) BEFORE the memory that the pointer points to are a length 66 * DWORD. One must therefore avoid pointer arithmetic and always use 67 * SysAllocString and the like to deal with BSTR pointers, which manage 68 * that DWORD correctly. 69 * 70 * For platforms other than Windows, we provide our own versions of the 71 * Sys* functions in Main/xpcom/helpers.cpp which do NOT use length 72 * prefixes though to be compatible with how XPCOM allocates string 73 * parameters to public functions. 74 * 75 * The Bstr class hides all this handling behind a std::string-like interface 76 * and also provides automatic conversions to MiniString and Utf8Str instances. 77 * 78 * The one advantage of using the SysString* routines is that this makes it 79 * possible to use it as a type of member variables of COM/XPCOM components 80 * and pass their values to callers through component methods' output parameters 81 * using the #cloneTo() operation. Also, the class can adopt (take ownership of) 82 * string buffers returned in output parameters of COM methods using the 83 * #asOutParam() operation and correctly free them afterwards. 84 * 85 * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates 86 * between NULL strings and empty strings. In other words, Bstr("") and 87 * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory, 88 * reports a zero length and zero allocated bytes for both, and returns an 89 * empty C wide string from raw(). 60 * 61 * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions 62 * back and forth since most of VirtualBox and our libraries use UTF-8. 63 * 64 * To make things more obscure, on Windows, a COM-style BSTR is not just a 65 * pointer to a null-terminated wide character array, but the four bytes (32 66 * bits) BEFORE the memory that the pointer points to are a length DWORD. One 67 * must therefore avoid pointer arithmetic and always use SysAllocString and 68 * the like to deal with BSTR pointers, which manage that DWORD correctly. 69 * 70 * For platforms other than Windows, we provide our own versions of the Sys* 71 * functions in Main/xpcom/helpers.cpp which do NOT use length prefixes though 72 * to be compatible with how XPCOM allocates string parameters to public 73 * functions. 74 * 75 * The Bstr class hides all this handling behind a std::string-like interface 76 * and also provides automatic conversions to MiniString and Utf8Str instances. 77 * 78 * The one advantage of using the SysString* routines is that this makes it 79 * possible to use it as a type of member variables of COM/XPCOM components and 80 * pass their values to callers through component methods' output parameters 81 * using the #cloneTo() operation. Also, the class can adopt (take ownership 82 * of) string buffers returned in output parameters of COM methods using the 83 * #asOutParam() operation and correctly free them afterwards. 84 * 85 * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates 86 * between NULL strings and empty strings. In other words, Bstr("") and 87 * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory, 88 * reports a zero length and zero allocated bytes for both, and returns an 89 * empty C wide string from raw(). 90 * 91 * @note All Bstr methods ASSUMES valid UTF-16 or UTF-8 input strings. 92 * The VirtualBox policy in this regard is to validate strings coming 93 * from external sources before passing them to Bstr or Utf8Str. 90 94 */ 91 95 class Bstr … … 301 305 * If the member string is empty, this allocates an empty BSTR in *pstr 302 306 * (i.e. makes it point to a new buffer with a null byte). 303 */ 304 void detachTo(BSTR *pstr) 307 * 308 * @param pbstrDst The BSTR variable to detach the string to. 309 * 310 * @throws std::bad_alloc if we failed to allocate a new empty string. 311 */ 312 void detachTo(BSTR *pbstrDst) 305 313 { 306 314 if (m_bstr) 307 *p str= m_bstr;315 *pbstrDst = m_bstr; 308 316 else 309 317 { 310 318 // allocate null BSTR 311 *p str= ::SysAllocString((const OLECHAR *)g_bstrEmpty);319 *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty); 312 320 #ifdef RT_EXCEPTIONS_ENABLED 313 if (!*p str)321 if (!*pbstrDst) 314 322 throw std::bad_alloc(); 315 323 #endif … … 322 330 * Takes the ownership of the returned data. 323 331 */ 324 BSTR *asOutParam()332 BSTR *asOutParam() 325 333 { 326 334 cleanup(); … … 352 360 * 353 361 * If the source is empty, this sets the member string to NULL. 354 * @param rs 355 */ 356 void copyFrom(const OLECHAR *rs) 357 { 358 if (rs && *rs) 362 * 363 * @param a_bstrSrc The source string. The caller guarantees 364 * that this is valid UTF-16. 365 * 366 * @throws std::bad_alloc - the object is representing an empty string. 367 */ 368 void copyFrom(const OLECHAR *a_bstrSrc) 369 { 370 if (a_bstrSrc && *a_bstrSrc) 359 371 { 360 m_bstr = ::SysAllocString( rs);372 m_bstr = ::SysAllocString(a_bstrSrc); 361 373 #ifdef RT_EXCEPTIONS_ENABLED 362 374 if (!m_bstr) … … 375 387 * 376 388 * If the source is empty, this sets the member string to NULL. 377 * @param rs 378 */ 379 void copyFrom(const char *rs) 380 { 381 if (rs && *rs) 382 { 383 PRTUTF16 s = NULL; 384 ::RTStrToUtf16(rs, &s); 385 #ifdef RT_EXCEPTIONS_ENABLED 386 if (!s) 387 throw std::bad_alloc(); 388 #endif 389 copyFrom((const OLECHAR *)s); // allocates BSTR from zero-terminated input string 390 ::RTUtf16Free(s); 391 } 392 else 393 m_bstr = NULL; 389 * 390 * @param a_pszSrc The source string. The caller guarantees 391 * that this is valid UTF-8. 392 * 393 * @throws std::bad_alloc - the object is representing an empty string. 394 */ 395 void copyFrom(const char *a_pszSrc) 396 { 397 copyFromN(a_pszSrc, RTSTR_MAX); 394 398 } 395 399 … … 397 401 * Variant of copyFrom for sub-string constructors. 398 402 * 399 * @param a_pszSrc The source string. 403 * @param a_pszSrc The source string. The caller guarantees 404 * that this is valid UTF-8. 400 405 * @param a_cchMax The maximum number of chars (not 401 406 * codepoints) to copy. If you pass RTSTR_MAX 402 407 * it'll be exactly like copyFrom(). 403 * @throws std::bad_alloc 408 * 409 * @throws std::bad_alloc - the object is representing an empty string. 404 410 */ 405 411 void copyFromN(const char *a_pszSrc, size_t a_cchSrc); … … 417 423 418 424 419 //////////////////////////////////////////////////////////////////////////////// 425 420 426 421 427 /** 422 * String class used universally in Main for UTF-8 strings. 423 * 424 * This is based on iprt::MiniString, to which some functionality has been 425 * moved. Here we keep things that are specific to Main, such as conversions 426 * with UTF-16 strings (Bstr). 427 * 428 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings 429 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) 430 * behave the same. In both cases, MiniString allocates no memory, reports 431 * a zero length and zero allocated bytes for both, and returns an empty 432 * C string from c_str(). 428 * String class used universally in Main for UTF-8 strings. 429 * 430 * This is based on iprt::MiniString, to which some functionality has been 431 * moved. Here we keep things that are specific to Main, such as conversions 432 * with UTF-16 strings (Bstr). 433 * 434 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings 435 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) behave the 436 * same. In both cases, MiniString allocates no memory, reports 437 * a zero length and zero allocated bytes for both, and returns an empty 438 * C string from c_str(). 439 * 440 * @note All Utf8Str methods ASSUMES valid UTF-8 or UTF-16 input strings. 441 * The VirtualBox policy in this regard is to validate strings coming 442 * from external sources before passing them to Utf8Str or Bstr. 433 443 */ 434 444 class Utf8Str : public iprt::MiniString … … 558 568 protected: 559 569 560 void copyFrom(CBSTR s);570 void copyFrom(CBSTR a_pbstr); 561 571 562 572 friend class Bstr; /* to access our raw_copy() */ -
trunk/src/VBox/Main/glue/string.cpp
r35128 r36428 53 53 size_t cwc; 54 54 int vrc = ::RTStrCalcUtf16LenEx(a_pszSrc, a_cchMax, &cwc); 55 AssertRCReturnVoid(vrc); /* throw instead? */ 55 if (RT_FAILURE(vrc)) 56 { 57 /* ASSUME: input is valid Utf-8. Fake out of memory error. */ 58 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTStrNLen(a_pszSrc, a_cchMax), a_pszSrc)); 59 throw std::bad_alloc(); 60 } 56 61 57 62 m_bstr = ::SysAllocStringByteLen(NULL, cwc * sizeof(OLECHAR)); 58 if (m_bstr) 63 if (RT_UNLIKELY(!m_bstr)) 64 throw std::bad_alloc(); 65 66 PRTUTF16 pwsz = (PRTUTF16)m_bstr; 67 vrc = ::RTStrToUtf16Ex(a_pszSrc, a_cchMax, &pwsz, cwc + 1, NULL); 68 if (RT_FAILURE(vrc)) 59 69 { 60 PRTUTF16 pwsz = (PRTUTF16)m_bstr; 61 vrc = ::RTStrToUtf16Ex(a_pszSrc, a_cchMax, &pwsz, cwc + 1, NULL); 62 if (RT_FAILURE(vrc)) 63 { 64 /* This should not happen! */ 65 AssertRC(vrc); 66 cleanup(); 67 } 70 /* This should not happen! */ 71 AssertRC(vrc); 72 cleanup(); 73 throw std::bad_alloc(); 68 74 } 69 else70 throw std::bad_alloc();71 75 } 72 76 … … 80 84 size_t cb = length() + 1; 81 85 *pstr = (char*)nsMemory::Alloc(cb); 82 if ( !*pstr)86 if (RT_UNLIKELY(!*pstr)) 83 87 throw std::bad_alloc(); 84 88 memcpy(*pstr, c_str(), cb); … … 137 141 * copying from a UTF-16 string. 138 142 * 139 * As with the iprt::ministring::copyFrom() variants, this unconditionally 140 * sets the members to a copy of the given other strings and makes141 * no assumptions about previous contents. This can therefore be used142 * both in copy constructors, when member variables have no defined143 * value, and inassignments after having called cleanup().143 * As with the iprt::ministring::copyFrom() variants, this unconditionally sets 144 * the members to a copy of the given other strings and makes no assumptions 145 * about previous contents. This can therefore be used both in copy 146 * constructors, when member variables have no defined value, and in 147 * assignments after having called cleanup(). 144 148 * 145 149 * This variant converts from a UTF-16 string, most probably from 146 150 * a Bstr assignment. 147 151 * 148 * @param s 152 * @param a_pbstr The source string. The caller guarantees that this 153 * is valid UTF-16. 154 * 155 * @sa iprt::MiniString::copyFromN 149 156 */ 150 void Utf8Str::copyFrom(CBSTR s)157 void Utf8Str::copyFrom(CBSTR a_pbstr) 151 158 { 152 if ( s && *s)159 if (a_pbstr && *a_pbstr) 153 160 { 154 int vrc = RTUtf16ToUtf8Ex((P RTUTF16)s, // PCRTUTF16 pwszString161 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr, 155 162 RTSTR_MAX, // size_t cwcString: translate entire string 156 163 &m_psz, // char **ppsz: output buffer 157 164 0, // size_t cch: if 0, func allocates buffer in *ppsz 158 165 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator. 159 if (RT_FAILURE(vrc)) 166 if (RT_SUCCESS(vrc)) 167 m_cbAllocated = m_cch + 1; 168 else 160 169 { 161 if ( vrc == VERR_NO_STR_MEMORY 162 || vrc == VERR_NO_MEMORY 163 ) 164 throw std::bad_alloc(); 170 if ( vrc != VERR_NO_STR_MEMORY 171 && vrc != VERR_NO_MEMORY) 172 { 173 /* ASSUME: input is valid Utf-16. Fake out of memory error. */ 174 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr)); 175 } 165 176 166 // @todo what do we do with bad input strings? throw also? for now just keep an empty string167 177 m_cch = 0; 168 178 m_cbAllocated = 0; 169 179 m_psz = NULL; 180 181 throw std::bad_alloc(); 170 182 } 171 else172 m_cbAllocated = m_cch + 1;173 183 } 174 184 else
Note:
See TracChangeset
for help on using the changeset viewer.